Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unexpected behavior with template type alias in VS2015

The following code compiles with VS15 Community and prints out "Hello".

#include <functional>
#include <iostream>

template<typename T>
using void_template_alias_t = void;

template<typename T>
using Func = std::function<void( T )>;

template<typename T>
using FuncVoid = Func<void_template_alias_t<T>>;

int main()
{
    FuncVoid<void> hello = [] { std::cout << "Hello\n"; };
    hello();
}

I think this is not allowed to compile.

I was playing around, the code was a bit more complex. I naively expected this to work, but suddenly realized that this code should not compile because you can't make a Func<void> (or am I wrong with this?).

  • Did I found a magic workaround?
  • Is this a new behavior from the C++14 standard?
  • Or is it simply a compiler bug?

Edit: The following more simplified version does not compile.

#include <functional>
#include <iostream>

template<typename T>
using Func = std::function<void( T )>;

int main()
{
    Func<void> hello = [] { std::cout << "Hello\n"; };
    hello();
}
  • So why is the code above compiling and working as I first expected?
  • Is it a correct implementation, if not, how would it look like?
like image 240
DaBrain Avatar asked Oct 17 '15 18:10

DaBrain


1 Answers

Or is it simply a compiler bug?

That. As mentioned by @T.C., CWG #577 is relevant:

[…] there was some concern expressed over the treatment of function templates and member functions of class templates if the C++ rule were changed: for a template parameter T, would a function taking a single parameter of type T become a no-parameter function if it were instantiated with T = void?

This is a justified complaint, but unfortunate for you, member functions/member function templates and type-ids were affected equally by the resolution:

A parameter list consisting of a single unnamed parameter of non-dependent type void is equivalent to the an empty parameter list.

thus both your snippets are ill-formed, as the parameter's type is indeed dependent.


Is it a correct implementation, if not, how would it look like?

There is no correct implementation. If you need a function type with an empty parameter list, you'll have to specify that independent from template parameters.

So why is the code above compiling and working as I first expected?

My best guess: VC++ does the substitution of void_template_alias_t<T> after assuring that the parameter type is not a dependent type "cv void", but before making the "void -> empty list transformation". However, it's often hard to comprehend how VC++ (or any compiler, for that matter) thinks internally.

like image 51
Columbo Avatar answered Nov 02 '22 22:11

Columbo