Strange behaviour of is_same_template on template aliases
Asked Answered
A

1

5

The following program...

#include <iostream>
#include <type_traits>

template <typename T>
struct Template{};

template <typename T>
using Alias = Template<T>;

template
    <
        template <typename>
        class T1,
        template <typename>
        class T2
    >
struct is_same_template : std::false_type{};

template
    <
        template <typename>
        class T
    >
struct is_same_template<T, T> : std::true_type{};

int main() {
    std::cout << std::boolalpha;
    std::cout << "Template == Template: " << is_same_template<Template, Template>::value << std::endl;
    std::cout << "Template == Alias: " << is_same_template<Template, Alias>::value << std::endl;
    std::cout << "Alias == Alias: " << is_same_template<Alias, Alias>::value << std::endl;
}

...outputs...

Template == Template: true
Template == Alias: false
Alias == Alias: true

...compiled with g++ 4.8.1, clang 3.4 and vc++ 18.00.21005.1.

Is it a bug in these compilers or a requirement of the standard?

Anaya answered 6/4, 2014 at 9:14 Comment(11)
What is your expected output?Donough
@JohnZwinck true/true/true of course as it is for type aliases and std::is_same.Anaya
Try adding ... to the typenames in your is_same_template. Now add template<T,U>foo and bar<T>=foo<T,T>. What should happen to is_same_template<foo,bar>?Greige
@Yakk I think in this case the program should outputs false (and it does). But in your example templates arguments count of a template and its alias are even unequal. How can they be equivalent in such case? What do you mean here?Anaya
It's not surprising to me... only the specializations of the alias template are type aliases. The alias template itself is a distinct template. See [temp.alias] and the discussion in the original proposalSmoothspoken
@Smoothspoken Thank you for this reference. As I understand the first variant of alias templates was chosen in C++11 standard (but without the possibility of alias template specialization). But I can't find the exact place in standard where this behavior is explicitly specified (even in [temp.alias] paragraph). Do you mean this sentence: 'The name of the alias template is a template-name.'?Anaya
I don't think it's specified explicitly. But there's no rule that under some circumstances, an alias template shall be a template alias (i.e. another name for a class template). Consider template<class T> using vec = std::vector<T>; (is that a template alias?) or template<class T> using Templ = Template<T*>; (is that a template alias?). A special rule would be required to specify exactly those cases where an alias template is a template alias.Smoothspoken
@Smoothspoken Thank you very much for your explanation! I see now, you are probably right that there is no special rule for exact template synonyms. And your reference is very interesting. Thank you again!Anaya
You're welcome :) IIRC there've been some discussions relating to this topic already on SO, but I'm not sure what to search for to find them.Smoothspoken
@Smoothspoken Can I ask a question about your answer to the referenced question?Anaya
I withdrew that reference (= deleted the comment) when I realized it's a different aspect of alias templates ;) Of course you can ask a question, preferably as a comment to that answer (or as a new SO Question).Smoothspoken
T
3

That is the behavior required by the Standard and it's perfectly logical. A alias template is not a template alias (despite intended by some to be). Initially there appears to have been some confusion even in the Standard about this, see http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1244 .

In the currently Standardized form, an alias template is like its non-templated counter part: It aliases a type. In the template version, the type may be dependent.

And it is immediately substituted. For example Alias<T> with T being itself a template parameter will be the dependent type Template<T> - in this sense the name alias template might be a bit confusing, because it suggests that there will be alias declaration instantiated at some point. But actually the alias pattern is substitued immediately - in this sense the templated version is more like a dependent alias declaration that always exists and does not need to be instantiated, rather than being an alias declaration template.

On that end, it becomes a bit philosophical what precisely we mean with those terms, though.

Type answered 6/4, 2014 at 15:30 Comment(3)
Thank you. So the conclusion is that the full analogue of a typedef for templates is missing in the current version of the standard (I mean simple cases such as exact synonyms of templates, like template <typename T> using Alias = Template<T>;), isn't it? Is it any known workaround for this problem?Anaya
@Anaya there is no workaround. You could ask for template aliases like using Alias = Template; on std-proposals if you wish to have them.Type
Sadly. Your suggestion is interesting. I'll try to realize it.Anaya

© 2022 - 2024 — McMap. All rights reserved.