我有一个带有template参数的类,我想调用它的一个方法.看起来像这样:
template <typename T> class Foo { public: void doSomething() { for (auto& t: ts) { t.doSomething(); } } private: std::vector<T> ts; };
这是有效的,但是我想使doSomething()const如果T本身是const(假定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(); } }
它工作正常,但它有一个代码重复.有什么办法可以避免吗?
解决方法
虽然不完美在这里是一个解决方法:我们有一个非const成员_doSomething(),其中我们的代码是相同的const和非const,除了在底层对象上调用的函数.既然这个成员是非const,我们必须const_cast这个从const Foo调用它.
由于_doSomething中的代码是const安全的,所以(const_)cast const是安全的.
你的代码也不会为const编译,因为你不能有一个const的向量.一个向量的元素必须是可分配的,哪些常量类型通常不是(他们真的不应该,但是:https://stackoverflow.com/a/17313104/258418).
您可能需要考虑std :: vector< T *>而不是std :: vector>. (即存储指针而不是向量中的对象)
#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; }