别名模板是否被视为与原始模板相同的模板模板参数?

DNK*_*Kpp 3 c++ template-specialization template-templates

当我在玩的时候,我偶然发现了下面的代码片段,令人惊讶的是,它与我的期望不符。

#include <tuple>
#include <type_traits>

template <class... Ts>
using myTuple = std::tuple<Ts...>;

template <template <class...> class Lhs, template <class...> class Rhs>
struct is_same
    : public std::false_type
{};

template <template <class...> class T>
struct is_same<T, T>
    : public std::true_type
{};

int main() {
    static_assert(is_same<myTuple, std::tuple>::value, "not same");
}
Run Code Online (Sandbox Code Playgroud)

我把它放在godbolt上并尝试用 3 个不同的编译器(clang、msvc 和 gcc)编译它,并收到了混合的结果。

铛:

<source>:18:5: error: static_assert failed due to requirement 'is_same<myTuple, std::tuple>::value' "not same"
static_assert(is_same<myTuple, std::tuple>::value, "not same");
^             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)

微软VC:

<source>(18): error C2338: static_assert failed: 'not same'
Run Code Online (Sandbox Code Playgroud)

海湾合作委员会:

(no errors)
Run Code Online (Sandbox Code Playgroud)

现在我问自己,哪一种行为是正确的?我希望两个参数相同,因此使用专业化,因为别名通常与原始类型没有不同。如果这不是正确的论点,我想知道为什么。

use*_*522 6

GCC 对此是错误的,而 Clang 和 MSVC 是正确的。应该static_assert会失败。

myTuple不是模板的别名std::tuple。模板没有别名,只有类型有别名。

std::tuplemyTuple是两个不同的模板,一个是类模板,另一个是别名模板。别名模板不这么称呼,因为它们是其他模板的别名。之所以这样称呼它们,是因为别名模板的每个特化都是一个(类型)别名。

具有相同模板参数列表的两个模板的每个特化碰巧会导致引用相同类型的内容,这与这里无关。true推导 的两个不同值(即模板)时,重载推导应该失败T

但请参阅开放(但旧)的CWG 问题 1286,该问题考虑使您正在使用的表单的某些别名模板等效于其定义中使用的类模板。我想这也应该会影响模板参数推导,以考虑为“一致”推导的两个值T。该问题还链接到已解决的CWG 问题 1244,该问题确认别名和类模板不等效,因此(我想说)对于模板参数推导的目的也不“一致”。

  • @AdrianMole不,所有编译器(或者至少是GCC和Clang,正如我可以测试的那样)都同意`std::is_same&lt;myTuple, std::tuple&gt;::value`格式不正确,而不是它是错误的。OP 必须推出自己的“is_same”,因为“std::is_same”只能比较类型,而不能比较模板。 (4认同)