首页 > 解决方案 > c++ type alias not working when testing specialization

问题描述

Using C++, trying to implement: is_specialization_of

template<typename T, template<typename...> class Template>
struct is_specialization_of : std::false_type {};

template<template<typename...> class Template, typename... Tn>
struct is_specialization_of<Template<Tn...>, Template> : std::true_type {};

template<typename... Tn>
struct tstruct {};

template<typename... Tn>
using ustruct = tstruct<Tn...>;

int main( int argc, char **argv )
{
    printf( "test u<int> against u, return %s\n", is_specialization_of<ustruct<int>, ustruct>::value ? "true" : "false" );
    printf( "test u<int> against t, return %s\n", is_specialization_of<ustruct<int>, tstruct>::value ? "true" : "false" );
    printf( "test t<int> against u return %s\n", is_specialization_of<tstruct<int>, ustruct>::value ? "true" : "false" );
    printf( "test t<int> against t, return %s\n", is_specialization_of<tstruct<int>, tstruct>::value ? "true" : "false" );
    getchar();
    return 0;
}

Return:

test u<int> against u, return false
test u<int> against t, return true
test t<int> against u return false
test t<int> against t, return true

Looks like the type alias is not considered exactly as the original type

I am using Visual Studio Community 2017

Microsoft (R) C/C++ Optimizing Compiler Version 19.15.26732.1 for x64

However when trying to compile the same code using gcc, it returns:

test u<int> against u, return true
test u<int> against t, return true
test t<int> against u return true
test t<int> against t, return true

Is there anything I can do for a workaround?

标签: c++templatesspecializationtype-alias

解决方案


Looks like the type alias is not considered exactly as the original type, or did I miss something?

The alias specialization is exactly the type it stands for. But the alias tempalte is an entirely distinct template. The reason for your output is specified by [temp.alias]

1 A template-declaration in which the declaration is an alias-declaration declares the identifier to be an alias template. An alias template is a name for a family of types. The name of the alias template is a template-name.

2 When a template-id refers to the specialization of an alias template, it is equivalent to the associated type obtained by substitution of its template-arguments for the template-parameters in the type-id of the alias template.

If we examine your test cases with the above two paragraphs in mind, we see that:

  1. "test u<int> against u" - ustruct<int> is equivalent to specifying tstruct<int> directly. And tstruct<int> is not a specialization of ustruct. The trait needs to evaluate to false.

  2. "test u<int> against t" - Here ustruct<int> is again equivalent to specifying tstruct<int> directly. And tstruct<int> is a specialization of tstruct. The trait should report true.

  3. "test t<int> against u" - tstruct<int> is not a specialization of ustruct, like we observed previously. The trait should report false.

  4. "test t<int> against t" - Should report true.

All your tests, when run in MSVC, conform to what the C++ standard says they should do. GCC is not conforming here, it's a compiler bug.


推荐阅读