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?

Constructor
  • 7,273
  • 2
  • 24
  • 66
  • What is your expected output? – John Zwinck Apr 06 '14 at 09:14
  • @JohnZwinck `true/true/true` of course as it is for type aliases and `std::is_same`. – Constructor Apr 06 '14 at 09:16
  • Try adding `...` to the `typename`s in your `is_same_template`. Now add `templatefoo` and `bar=foo`. What should happen to `is_same_template`? – Yakk - Adam Nevraumont Apr 06 '14 at 09:46
  • @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? – Constructor Apr 06 '14 at 09:53
  • 2
    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 proposal](http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2002/n1406.pdf) – dyp Apr 06 '14 at 11:05
  • @dyp 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*.'? – Constructor Apr 06 '14 at 11:55
  • 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 using vec = std::vector;` (is that a template alias?) or `template using Templ = Template;` (is that a template alias?). A special rule would be required to specify exactly those cases where an alias template is a template alias. – dyp Apr 06 '14 at 12:06
  • @dyp 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! – Constructor Apr 06 '14 at 12:23
  • 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. – dyp Apr 06 '14 at 12:28
  • @dyp Can I ask a question about your [answer](http://stackoverflow.com/questions/17392621/using-a-template-alias-instead-of-a-template-within-a-template/17393352#17393352) to the referenced question? – Constructor Apr 06 '14 at 12:31
  • 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). – dyp Apr 06 '14 at 12:34

1 Answers1

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.

Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
  • 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 using Alias = Template;`), isn't it? Is it any known workaround for this problem? – Constructor Apr 06 '14 at 17:07
  • @Constructor there is no workaround. You could ask for template aliases like `using Alias = Template;` on std-proposals if you wish to have them. – Johannes Schaub - litb Apr 06 '14 at 17:13
  • Sadly. Your suggestion is interesting. I'll try to realize it. – Constructor Apr 06 '14 at 17:30