Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++11 template alias as template template argument leads to different type?

We have observed a strange behaviour in the compilation of the follwing source code:

template<template<class> class TT> struct X { };
template<class> struct Y { };
template<class T> using Z = Y<T>;

int main() {
  X<Y> y;
  X<Z> z;
  z = y; // it fails here
}

This is a slightly modified example taken from the c++11 standard proposal for template aliases: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2258.pdf (See page 4) Also note that the proposal "declares y and z to be of the same type." In our interpretation it should therefore be possible to assign (or copy construct) z from y.

However, this code doesn't compile with gcc 4.8.1 nor with clang 3.3. Is this an error in the compiler or did we misunderstand the standard?

Thanks in advance, craffael et al ;)

P.S. The Clang error message is:

error: no viable overloaded '='

note: candidate function (the implicit copy assignment operator) not viable: no known conversion from 'X<template Y>' to 'const X<template Z>' for 1st argument
template<template<class> class TT> struct X { };

note: candidate function (the implicit move assignment operator) not viable: no known conversion from 'X<template Y>' to 'X<template Z>' for 1st argument
template<template<class> class TT> struct X { };
like image 936
craffael Avatar asked Oct 11 '13 09:10

craffael


People also ask

What is the difference between template Typename T and template T?

There is no difference. typename and class are interchangeable in the declaration of a type template parameter.

What is a type alias c++?

Type alias is a name that refers to a previously defined type (similar to typedef). Alias template is a name that refers to a family of types.

What is a template argument c++?

In C++ this can be achieved using template parameters. A template parameter is a special kind of parameter that can be used to pass a type as argument: just like regular function parameters can be used to pass values to a function, template parameters allow to pass also types to a function.

What is template argument deduction in C++?

Class Template Argument Deduction (CTAD) is a C++17 Core Language feature that reduces code verbosity. C++17's Standard Library also supports CTAD, so after upgrading your toolset, you can take advantage of this new feature when using STL types like std::pair and std::vector.


2 Answers

The current standard doesn't say so, but the intention is that y and z have the same type. There is an open Core Working Group issue for this: http://wg21.cmeerw.net/cwg/issue1286

like image 69
cmeerw Avatar answered Oct 19 '22 23:10

cmeerw


I think you are confusing a type and a template (or a template alias). You have Y, which is one template and Z, which is another one. If you think that Y == Z, you are wrong. Only if you turn them into types, those types are the same, e.g. Y<int> is the same type as Z<int>. In your example:

template<class T> struct X { };

template<class> struct Y { };
template<class T> using Z = Y<T>;

int main() {
  X<Y<int>> y;
  X<Z<int>> z;
  z = y; // works
}

In your original code you referred to them with X<Y> and X<Z>, but as Y is not the same as Z, so are X<Y> and X<Z> different types.

like image 20
Daniel Frey Avatar answered Oct 20 '22 01:10

Daniel Frey