如何根据模板参数创建一个方法const?

How to make a method const based on the template parameter?

我有一个带有模板参数的 class,我想调用它的一个方法。它看起来像这样:

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

这行得通,但如果 T 本身是常量,我想使 doSomething() 常量(假设 T::doSomething() 也是常量)。我找到了一个可能的解决方案(基于 ),但我不喜欢它。

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 是相同的,除了在底层对象上调用的函数。因为这个成员是 non const 我们必须 const_cast this 从 const Foo 中调用它。

由于 _doSomething 中的代码是 const 安全的,因此 (const_)cast const 是安全的。

您的代码也不会针对 const 进行编译,因为您不能拥有 constvector。向量的元素必须是可分配的,const types 通常 不是(它们确实不应该,但是:)。
您可能想要考虑 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; 
    T test;
};

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

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