C++: Reference/pointer 以成员变量作为模板参数

C++: Reference/pointer to member variable as template parameter

首先,我有这样的东西:

class Test {
    std::vector<int> a, b;
    void caller(...) { callee(...); }
    void callee(...) { /* Do stuff with 'a' */ }
}

我想要的是拥有一个与 callee 完全相同的函数,但用于向量 b。为此,有两个明显的解决方案:

出于好奇,我去寻找模板部分,我注意到它可以用于

lvalue reference type

pointer type

pointer to member type

所以我尝试这样做:

class Test {
    std::vector<int> a, b;
    void caller(...) { callee<a>(...); }
    template <std::vector<int> &x> void callee(...) { /* Do stuff with 'x' */ }
}

但我明白了

error: use of ‘this’ in a constant expression

有什么方法可以通过引用或指针来实现吗?

顺便说一句,我想要的可以看作是一个函数范围的#define

简单地使用外观:

class Test {
    std::vector<int> a, b;
    void caller_a(...) { callee(a); }
    void caller_b(...) { callee(b); }
    void callee(std::vector<int> &a_or_b, ...) {
    }
}

callee() 将引用其参数,该参数将作为一个或另一个 class 成员传入。

您不能将对数据成员的引用用作模板参数:模板是编译时的,this 的值直到运行时才知道。换句话说,您需要为 Test.

类型的每个 运行时对象 单独实例化(单独的二进制代码)

可以做的是用数组替换ab,并通过索引将callee模板化到这个数组中:

class Test {
    std::array<std::vector<int>, 2> ab;
    void caller(...) { callee<0>(...); }
    template <size_t idx>
    void callee(...) { /* Do stuff with 'ab[idx]' */ }
}

这样,您只会得到 callee 的两个实例化(一个用于 0,一个用于 1),索引在编译时完成(或至少可行) .

按照与@Angew 的回答相同的逻辑,您也可以使用 std::tuple,这与元组一样非常有趣,您还可以在被调用函数中使用不同类型的容器:

class Test {
    std::tuple<std::vector<int>, std::list<int> > ab;
    void caller(...) { callee<0>(...); }
    template <size_t idx>
    void callee(...) { 
    ...
    auto aIt = std::get<idx>(ab).begin(); // gets either the vector or the list depending on template value
    ...
    }
}

数组甚至元组,但不喜欢旧的指向成员的指针?

class Test {
    std::vector<int> a, b;

    void caller(/*...*/) { callee<&Test::a>(/*...*/); }

    template <std::vector<int> Test::*vec>
    void callee(/*...*/) { /* Do stuff with `(this->*vec)` */ }
};