C++20 Concept检查模板方法失败:非const左值引用无法绑定右值
解决C++20 Concept无法识别模板方法的问题
问题重现
你定义了如下接口、实现类和目标类:
template <typename T> class Other { public: virtual auto make() -> T = 0; }; class Impl : public Other<int> { public: auto make() -> int { return 1; } }; class Thing { public: template <typename T> auto some(Other<T>& other) -> T { return other.make(); } };
尝试用以下Concept验证Thing是否符合要求:
template <typename T> concept IsCorrect = requires (T v) { { v.template some(Impl{}) } -> std::same_as<int>; }; static_assert(IsCorrect<Thing>); // 编译失败
编译错误显示v.template some(Impl{})无法匹配到对应的成员函数。
错误原因
Thing::some的参数是非const左值引用(Other<T>&),而你在Concept中传递的Impl{}是临时对象(右值),C++中右值无法绑定到非const左值引用,因此模板方法匹配失败,Concept断言不通过。
修改方案
方案1:调整参数为可接受右值的引用类型
修改Thing::some的参数为const左值引用(需要同步修改Other的虚函数为const成员):
// 修改Other类的make为const成员 template <typename T> class Other { public: virtual auto make() const -> T = 0; }; // Impl的make对应添加const class Impl : public Other<int> { public: auto make() const -> int { return 1; } }; // Thing::some参数改为const引用 class Thing { public: template <typename T> auto some(const Other<T>& other) -> T { return other.make(); } }; // 此时Concept可以正常工作,或更通用地使用std::declval template <typename T> concept IsCorrect = requires (T v) { { v.template some(std::declval<const Impl&>()) } -> std::same_as<int>; };
方案2:在Concept中传递左值
不修改Thing的代码,改为在Concept中传递左值引用或左值变量:
// 方式A:在requires中声明左值变量 template <typename T> concept IsCorrect = requires (T v, Impl impl) { { v.template some(impl) } -> std::same_as<int>; }; // 方式B:用std::declval获取左值引用 template <typename T> concept IsCorrect = requires (T v) { { v.template some(std::declval<Impl&>()) } -> std::same_as<int>; };
方案3:让Concept更通用(推荐)
如果你的需求是验证类型能处理任意Other<T>实例,而非仅Impl,可以直接用Other<int>&作为参数:
template <typename T> concept IsCorrect = requires (T v, Other<int>& other) { { v.template some(other) } -> std::same_as<int>; };
这样的Concept更贴合你“类型具备接受Other实例并返回其模板参数类型的模板方法”的核心需求。
内容的提问来源于stack exchange,提问作者larkwiot
相关产品推荐
相关产品推荐

