我想知道是否有更好的方法来解决这样的模板函数的代码重复问题
struct Z {
void doSomething() { std::cout << "non-const version\n"; }
void doSomething() const { std::cout << "const version\n"; }
};
void tempFunc( Z& z ) {
z.doSomething(); // calls non-const member function
}
void tempFunc( const Z& z ) {
z.doSomething(); // calls const member function
}
int main() {
Z z;
const Z cz;
tempFunc(z);
tempFunc(cz);
return 0;
}
如您所见, tempFunc 的两个定义是相同的,因此为了避免代码重复,我使用这样的约束在 C++20 下重写了该函数
void tempFunc( std::convertible_to<Z> auto&& z ) {
z.doSomething();
}
注意 std::is_convertible_to<> 的使用,它工作得很好,但我怀疑应该有一个标准(或者如果不是一个容易编写的约束)来使用 is_convertible_to<> 来限制参数仅匹配 const和非常量引用。
std::convertible_to
是错误的概念。您不想要可转换为Z
的东西。您需要 是 Z
的东西。
或者,不是特别是 is-a,因为
Z const
和 Z&&
都不是字面上的 Z
,但你也想允许它们。
为此,人们通常会写的是:
template <typename T, typename U>
concept DecaysTo = std::same_as<std::decay_t<U>, T>;
用作:
void tempFunc( DecaysTo<Z> auto&& z ) {
z.doSomething();
}
现在匹配任何类型
T
,使得 std::decay_t<T>
为 Z
。基本上就是Z [const][&|&&]
。这就是你想要的。