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
。为此,有两个明显的解决方案:
- 传递矢量
a
或 b
作为参数。但是,callee
是一个可以进行数百次调用的递归函数,将向量作为参数传递只是不必要的开销。
- 复制函数
callee
并使用向量 b
,这将是最好的选择,尽管 callee
是一个相当长的函数而且我会有很多重复代码。
出于好奇,我去寻找模板部分,我注意到它可以用于
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
.
类型的每个 运行时对象 单独实例化(单独的二进制代码)
你可以做的是用数组替换a
和b
,并通过索引将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)` */ }
};
首先,我有这样的东西:
class Test {
std::vector<int> a, b;
void caller(...) { callee(...); }
void callee(...) { /* Do stuff with 'a' */ }
}
我想要的是拥有一个与 callee
完全相同的函数,但用于向量 b
。为此,有两个明显的解决方案:
- 传递矢量
a
或b
作为参数。但是,callee
是一个可以进行数百次调用的递归函数,将向量作为参数传递只是不必要的开销。 - 复制函数
callee
并使用向量b
,这将是最好的选择,尽管callee
是一个相当长的函数而且我会有很多重复代码。
出于好奇,我去寻找模板部分,我注意到它可以用于
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
.
你可以做的是用数组替换a
和b
,并通过索引将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)` */ }
};