C++ “模板尾部结构升高”;嵌套名称说明符“中的类型不完整”;
我试图操作C++14C++ “模板尾部结构升高”;嵌套名称说明符“中的类型不完整”;,c++,templates,c++14,variadic-templates,template-meta-programming,C++,Templates,C++14,Variadic Templates,Template Meta Programming,我试图操作C++14integer\u序列,但运行时遇到一个错误I 我不明白。让我们从可读性的快捷方式开始 template <typename Int, Int...ints> using IS = std::integer_sequence<Int, ints...>; 现在我想定义尾部(lisp中的cdr): 模板结构尾部; 模板 结构尾部:是{}; 模板 结构尾部:尾部{}; 但这并不像预期的那样有效: // This works as expected st
integer\u序列
,但运行时遇到一个错误I
我不明白。让我们从可读性的快捷方式开始
template <typename Int, Int...ints>
using IS = std::integer_sequence<Int, ints...>;
现在我想定义尾部(lisp中的cdr):
模板结构尾部;
模板
结构尾部:是{};
模板
结构尾部:尾部{};
但这并不像预期的那样有效:
// This works as expected
static_assert(redsum< IS<unsigned, 2, 5, 12, 18> >::value == 2 + 5 + 12 + 18);
// This doesn't with an incomplete type error
static_assert(redsum< tail < IS<unsigned, 2, 5, 12, 18> > >::value == 5 + 12 + 18);// EDIT
//这工作正常
静态断言(redsum:value==2+5+12+18);
//这与不完整的类型错误无关
静态断言(redsum::value==5+12+18);//编辑
我不明白在这个用例中我的类型在哪里是不完整的。任何
解释或建议如何更好地编写它?所有的
redsum
模板专门化都希望tempate参数的类型为std::integer\u sequence
。虽然类tail
最终继承自std::integer\u sequence
,但它本身不会与专门化所期望的类型匹配,因此编译器会返回(未定义的)主模板。这种情况下的经典方法是在类模板专门化中定义一个嵌套类型,以终止递归:
template <typename Int, Int ...ints>
struct tail;
template <typename Int, Int i0, Int... ints>
struct tail<Int, i0, ints...> { using type = IS<Int, ints...>; };
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
template <typename Int, Int... ints>
struct tail<IS<Int, ints...>> : tail<Int, ints...> {};
模板
结构尾;
模板
结构尾部{using type=IS;};
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
模板
结构尾部:尾部{};
然后访问嵌套类型以获取此转换的结果:
redsum< tail < IS<unsigned, 2, 5, 12, 18> >::type >::value
// ~~~~~^
redsum::类型>::值
// ~~~~~^
Piotr(+1)为什么会出现错误
无论如何,如果您想只使用std::integer\u序列调用tail
tail<IS<long, 2L, 3L, 5L, 7L>>
并且将想要的类型定义为内部类型(正如Piotr所建议的那样),您可以通过一个专门化来实现它
template <typename Int, Int i0, Int... ints>
struct tail<IS<Int, i0, ints...>>
{ using type = IS<Int, ints...>; };
因此,如果将容器定义为
template <typename T, T...>
struct myList
{ };
相同的建议适用于redsum
;您可以将其定义为接收单个类型
template <typename>
struct redsum;
因此满足以下静态断言()
static_assert( std::is_same<redsum<myList<int, 2, 3, 5, 7>>::type,
myList<int, 17>>{}, "!" );
static_assert( redsum<myList<int, 2, 3, 5, 7>>::value == 17, "!" );
好啊我想我或多或少了解这个问题。我见过经典的方法,但对我来说,它似乎非常复杂。现在我知道为什么了。您是否有任何参考资料解释此匹配是如何执行的以及为什么在我的情况下不执行?如果您使用static\u assert(5+12+18==redsum::value,”)
而不是std::cout
,您的意图会更清楚。我猜是基于误解。@Julius-我确认:我的回答是基于误解;“对不起!”朱利叶斯补充道;希望这不会被误解,@Julius:谢谢你的想法!我正在修正我的问题+1.关于为什么问题中的方法失败的解释,请参见。@Julius-你是对的:Piotr的答案值得更清楚地提到最初失败的原因。修改答案。
template <typename Int, Int i0, Int... ints>
struct tail<IS<Int, i0, ints...>>
{ using type = IS<Int, ints...>; };
template <template <typename T, T...> class C,
typename Int, Int i0, Int... ints>
struct tail<C<Int, i0, ints...>>
{ using type = C<Int, ints...>; };
template <typename T, T...>
struct myList
{ };
static_assert( std::is_same<tail<myList<int, 2, 3, 5, 7>>::type,
myList<int, 3, 5, 7>>{}, "!");
template <typename>
struct redsum;
template <template <typename T, T...> class C,
typename Int, Int i0, Int i1, Int... ints>
struct redsum< C<Int, i0, i1, ints...> > :
redsum< C<Int, i0 + i1, ints...> >
{ };
template <template <typename T, T...> class C, typename Int, Int i0>
struct redsum<C<Int, i0> > : std::integral_constant< Int, i0 >
{ using type = C<Int, i0>; };
static_assert( std::is_same<redsum<myList<int, 2, 3, 5, 7>>::type,
myList<int, 17>>{}, "!" );
static_assert( redsum<myList<int, 2, 3, 5, 7>>::value == 17, "!" );
template <typename>
struct redsum;
template <template <typename T, T...> class C, typename Int, Int... ints>
struct redsum< C<Int, ints...> >
: std::integral_constant<Int, (ints + ...)>
{ using type = C<Int, (ints + ...)>; };