C++20:用Concept限制模板函数匹配const/非const引用以避免代码重复
解决模板函数代码重复的精准约束方案
你当前用std::convertible_to<Z>虽然能正常工作,但它的范围太宽泛——会允许任何可隐式转换为Z的类型,而你真正需要的是仅匹配Z的非const左值引用、const左值引用。以下是几种更精准的实现方案:
方案1:自定义Concept(最清晰直观)
通过自定义Concept明确限定参数为Z的左值引用(带/不带const):
#include <concepts> #include <type_traits> #include <iostream> struct Z { void doSomething() { std::cout << "non-const version\n"; } void doSomething() const { std::cout << "const version\n"; } }; template <typename T> concept ZLvalueRef = std::is_lvalue_reference_v<T> && std::same_as<std::remove_cv_t<std::remove_reference_t<T>>, Z>; void tempFunc(ZLvalueRef auto z) { z.doSomething(); } int main() { Z z; const Z cz; tempFunc(z); // 调用非const版本 tempFunc(cz); // 调用const版本 // tempFunc(Z{}); // 编译错误:右值引用不满足约束 return 0; }
这个Concept严格限制了参数必须是Z的左值引用(无论是否带const),拒绝右值引用和其他可转换类型。
方案2:模板参数直接约束CV修饰的Z
利用模板参数匹配Z或const Z,再结合左值引用:
#include <concepts> #include <iostream> struct Z { void doSomething() { std::cout << "non-const version\n"; } void doSomething() const { std::cout << "const version\n"; } }; template <typename CVZ> requires std::same_as<std::remove_cv_t<CVZ>, Z> void tempFunc(CVZ& z) { z.doSomething(); } int main() { Z z; const Z cz; tempFunc(z); tempFunc(cz); return 0; }
这里CVZ会被推导为Z或const Z,对应的CVZ&就是你需要的两种引用类型,同样拒绝非Z相关的参数。
方案3:inline约束组合(无需自定义Concept)
直接在函数参数里组合类型特征约束,适合简单场景:
#include <concepts> #include <type_traits> #include <iostream> struct Z { void doSomething() { std::cout << "non-const version\n"; } void doSomething() const { std::cout << "const version\n"; } }; void tempFunc(auto& z) requires std::same_as<std::remove_cv_t<decltype(z)>, Z> { z.doSomething(); } int main() { Z z; const Z cz; tempFunc(z); tempFunc(cz); return 0; }
auto&确保是左值引用,requires子句限定引用的底层类型是Z(忽略const修饰),实现和方案1一致的效果。
这三个方案都能精准匹配你需要的两种引用类型,避免std::convertible_to<Z>带来的过度宽松问题,同时消除了原重载函数的代码重复。
内容的提问来源于stack exchange,提问作者Ricardo Capurro
相关产品推荐
相关产品推荐

