Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

moving std::enable_if from parameters to template parameters

I am basically trying to do the same as std::enable_if : parameter vs template parameter but I can't get my code to compile.

I had a simple first version that has the std::enable_if in the parameters and which works fine:

#include <iostream>
#include <type_traits>

template <typename T>
void foo(T t, typename std::enable_if< std::is_same<T, int>::value >::type* = 0) {
  std::cout << "int" << std::endl;
}

template <typename T>
void foo(T t, typename std::enable_if< !std::is_same<T, int>::value >::type* = 0) {
  std::cout << "not int" << std::endl;
}

int main(int argc, char* argv[])
{
  foo(10);
  foo(10.1);
  return 0;
}

But I thought it might be more concise if the template stuff was in one place and wanted the enable_if out of the function arguments.

Now if I simply move the enable_if part I get the following:

#pragma warning(1 : 4519)

#include <iostream>
#include <type_traits>

template <typename T, typename std::enable_if< std::is_same<T, int>::value >::type = 0>
void foo(T t) {
  std::cout << "int" << std::endl;
}

template <typename T, typename std::enable_if< !std::is_same<T, int>::value >::type = 0>
void foo(T t) {
  std::cout << "not int" << std::endl;
}

int main(int argc, char* argv[])
{
  foo(10);
  foo(10.1);
  return 0;
}

The #pragma warning(1 : 4519) I needed because otherwise default arguments on a function template are an error in VS2010. The problem is it still doesn't compile. The first message was: error C2783: 'void foo(T)' : could not deduce template argument for '__formal' and even though I don't want to do that I tried explicitly stating which template I want by calling it using

  foo<int, int>(10);
  foo<double, double>(10.1);

but it still doesn't work and the new error is.

error C2975: 'foo' : invalid template argument for 'unnamed-parameter', expected compile-time constant expression

I hope somebody can tell me how to fix this and of course all comments on my style and other issues my code might have are welcome. :)

Extra question: Does anybody know why VS2010 does not allow default arguments on function templates by default?

like image 401
Sarien Avatar asked Aug 27 '12 12:08

Sarien


1 Answers

The problem is that the second template parameter in std::enable_if defaults to void. So your doing something which is pretty much the same as:

template <typename T, void = 0>

Which makes substitution fail always. You could use a non-type template argument of type int, which you can give a default 0 value:

template <typename T, typename std::enable_if< std::is_same<T, int>::value, int >::type = 0>

Do the same for both overloads, and it will work.

Demo here.

like image 69
mfontanini Avatar answered Sep 27 '22 21:09

mfontanini