如何在C++ concept中正确定义std::tuple类型的数据成员?
问题分析与解决方案
你的代码核心问题出在c3概念的定义上:
- 原代码中
template <typename t, typename... c1>的参数设计错误:typename... c1是一个独立的类型参数包,和你定义的c1概念没有关联,而且编译器调用f(_a)时无法推导出这个参数包,默认会当作空包处理,导致检查p_t.cs是否为std::tuple<>&,和实际的std::tuple<a2,a3>&类型不匹配,触发ERROR1。 - 后续ERROR2、ERROR3都是因为
c3约束不满足,导致函数f无法匹配调用。
正确实现方式
方式一:直接用c1 auto...约束tuple元素
利用C++20支持的概念参数语法,直接在std::tuple中指定元素需满足c1概念,同时约束cs成员的类型:
#include <concepts> #include <iostream> #include <tuple> template <typename t> concept c1 = requires(t p_t) { { p_t.i } -> std::same_as<int &>; }; // 修正后的c3:无需额外模板参数,直接约束cs是元素满足c1的tuple左值引用 template <typename t> concept c3 = requires(t p_t) { { p_t.cs } -> std::same_as<std::tuple<c1 auto...> &>; }; template <c1... t_c1> struct a1 { std::tuple<t_c1...> cs; }; struct a2 { int i{-9}; }; struct a3 { int i{8}; }; void f(c3 auto &p_c3) { std::cout << std::get<0>(p_c3.cs).i << std::endl; } int main() { a1<a2, a3> _a; f(_a); return 0; }
方式二:用辅助概念检查tuple元素
如果更倾向于显式的辅助概念,可以先定义一个检查tuple元素是否全部满足c1的concept,再约束cs成员:
#include <concepts> #include <iostream> #include <tuple> template <typename t> concept c1 = requires(t p_t) { { p_t.i } -> std::same_as<int &>; }; // 辅助concept:检查T是否是元素全满足c1的tuple template<typename T> concept TupleOfC1 = false; template<c1... Ts> concept TupleOfC1<std::tuple<Ts...>> = true; // 定义c3:约束cs是TupleOfC1类型的左值引用 template <typename t> concept c3 = requires(t p_t) { { p_t.cs } -> std::same_as<TupleOfC1&>; }; template <c1... t_c1> struct a1 { std::tuple<t_c1...> cs; }; struct a2 { int i{-9}; }; struct a3 { int i{8}; }; void f(c3 auto &p_c3) { std::cout << std::get<0>(p_c3.cs).i << std::endl; } int main() { a1<a2, a3> _a; f(_a); return 0; }
关键说明
- 两种方式都避免了原代码中多余的模板参数包,让编译器可以正确推导
cs成员的类型。 std::same_as<std::tuple<c1 auto...> &>的写法直接约束了cs是左值引用,且引用的tuple中每个元素都满足c1概念,这是C++20概念的原生支持语法。
内容的提问来源于stack exchange,提问作者canellas
相关产品推荐
相关产品推荐

