2015-05-19 48 views
10

我有一个带有模板参数的类,我想调用它的一个方法。它看起来是这样的:如何根据模板参数创建一个const方法?

template <typename T> 
class Foo { 
public: 
    void doSomething() { 
     for (auto& t: ts) { 
      t.doSomething(); 
     } 
    } 
private: 
    std::vector<T> ts; 
}; 

这工作,但我想使doSomething()常量如果T本身是常量(假设T::doSomething()将是const太)。我找到了一个可能的解决方案(基于this question),但我不喜欢它。

template <bool enabled = std::is_const<T>::value> 
typename std::enable_if<enabled, void>::type 
doSomething() const { 
    for (auto& t: ts) { 
     t.doSomething(); 
    } 
} 

template <bool enabled = !std::is_const<T>::value> 
typename std::enable_if<enabled, void>::type 
doSomething() { 
    for (auto& t: ts) { 
     t.doSomething(); 
    } 
} 

它工作正常,但它有一个代码重复。有什么办法可以避免它?

+0

作为workarround您可以添加'私营:属性(always_inline)_doSomething',并呼吁从你的'(常量)dosomething' – ted

回答

2

尽管这里不是完美的解决方法:我们有一个非常量成员_doSomething(),其中我们的代码与常量和非常量相同,除了在底层对象上调用的函数之外。由于这个成员是non const我们必须const_castthis从const Foo调用它。

由于_doSomething内部的代码是常量安全的,因此将(const_)强制const远离是安全的。

你的代码也不能编译为const,因为你不能有vectorconst。一个向量的元素必须是可分配的,其中const types通常是不是(它们确实不应该,但是:https://stackoverflow.com/a/17313104/258418)。
您可能需要考虑std::vector<T*>而不是std::vector<T>。 (即存储指针,而不是矢量对象)

#include <iostream> 
#include <vector> 

using namespace std; 

class Bar { 
public: 
    Bar() {} 
    void doSomething() const { 
     std::cout << "const" << endl; 
    } 

    void doSomething() { 
     std::cout << "NON const" << endl; 
    } 
}; 


template <typename T> 
class Foo { 
    void _doSomething() { 
     /*for (auto& t: ts) { 
      t.doSomething(); 
     }*/ 
     test.doSomething(); 
    } 
public: 
    Foo()/*T element) : ts({element})*/ {} 

    template <bool enabled = std::is_const<T>::value> 
    typename std::enable_if<enabled, void>::type 
    doSomething() const { 
     const_cast<typename std::remove_const<Foo<T>>::type*>(this)->_doSomething(); 
    } 

    template <bool enabled = !std::is_const<T>::value> 
    typename std::enable_if<enabled, void>::type 
    doSomething() { 
     _doSomething(); 
    } 
private: 
    //std::vector<T> ts; https://stackoverflow.com/a/17313104/258418 
    T test; 
}; 

int main() 
{ 
    Foo<Bar> nonConstInst; 
    Foo<const Bar> ConstInst; 

    nonConstInst.doSomething(); 
    ConstInst.doSomething(); 
    return 0; 
} 
+1

真,这不是” t为矢量工作。实际上我在那里使用'shared_ptr'('unique_ptr'会更好),所以const函数总是可以工作的。尽管如此,包含的对象是对象状态的一部分,所以我想'doSomething()'是非const的,如果我改变包含对象的状态。但无论如何,你的解决方案的工作原理,我甚至不需要'const_cast'。 – petersohn

相关问题