模板头类型推导原理问题

问题描述 投票:0回答:1

我试图理解为什么编译器无法使用如下代码进行所有推导:

template <typename tuple_types>
struct TupleX;

template <typename... head_types, typename tail_type>
struct TupleX< std::tuple<head_types..., tail_type> > // Error
{
    using Tail = tail_type;
};

using FooX = std::tuple<int, float, double>;
using BarX = typename TupleX<FooX>::Tail;

Visual C++ 2022 无法使用以下命令构建它:

error C2027: use of undefined type 'TupleX<FooX>' see declaration of 'TupleX<FooX>'
error C2061: syntax error: identifier 'Tail'

虽然顺序相反,但推导仍按预期进行:

template <typename tuple_types>
struct TupleX;

template <typename head_type, typename... tail_types>
struct TupleX< std::tuple<head_type, tail_types...> >
{
    using Head = head_type;
};

using FooX = std::tuple<int, float, double>;
using BarX = typename TupleX<FooX>::Head;

static_assert(std::is_same_v<BarX, std::tuple_element_t<0, FooX> >);

考虑到以上所有内容,我提出了几个问题,希望是正确的。

  1. 我提出的实现中是否存在一些逻辑错误?(我理解语法错误,但我想知道表达式中是否违反了一些基本原则)
  2. 其他编译器支持这种推导吗?
  3. 是标准定义的情况吗?(我忽略了一些文档,但没有找到答案)
c++ c++20 c++-templates
1个回答
0
投票

为什么编译器不能使用这样的模式

因为模板参数会消耗所有传递的模板参数。这会导致

tail_type
在示例的第一种情况下为空。但由于
tail_type
是非参数包,所以不能留空。

我提出的实现中是否存在一些逻辑错误?

问题在于你的逻辑的实现。

特别是,在第一种情况下

head_type
是一个参数包,这意味着它消耗所有传递的参数参数(此处为
FooX
)。这反过来意味着
tail_type
将为空,但这是不允许的,因为
tail_type
不是参数包,因此 不能留空

因此,在这种情况下,专业化不是匹配,唯一的匹配是将要使用的主要模板。但由于您只有主模板的声明,因此我们收到了提到的不完整错误。


第二种情况有效,因为现在

tail_type
是一个参数包并且可以留空。在这种情况下传递的
FooX
将与
head_type
匹配。

© www.soinside.com 2019 - 2024. All rights reserved.