Rules for implicit conversion of template arguments

Go To StackoverFlow.com

12

If you overload a function and then call it with an argument that perfectly matches one of the overloads

int f(int){return 3;}
int f(bool){return 4;}
...        //inside main()
f(1);      //Calls f(int)

the compiler simply chooses this (perfect) match before attempting any implicit conversions. However I've been trying to overload a function tempĺate as in

template <bool veracity>
int f(){return 1;}

template <int amount>
int f(){return 2;}

...        //inside main()
f<1>();

but the compiler keeps complainning about ambiguous call to the overloaded f(), stating it could be either f<true>() or f<1>(). Shouldn't the compiler just choose the perfect match, instead of trying to convert 1 to true ?

I was under the impression that implicit conversion for template arguments was actually more restrictive than implicit conversion of function arguments. Is there a way to get around this problem?

2012-04-05 15:21
by Malabarba


8

The argument you're supplying isn't a type, it's a value, so the rules are a bit different -- you need to apply the rules for non-type arguments. For non-type arguments, implicit conversions are allowed. §14.3.2/5:

The following conversions are performed on each expression used as a non-type template-argument. If a non-type template-argument cannot be converted to the type of the corresponding template-parameter then the program is ill-formed.

— For a non-type template-parameter of integral or enumeration type, conversions permitted in a converted constant expression (5.19) are applied.

In C++03, the wording is marginally different, but the effect essentially identical (also §14.3.2/5):

— for a non-type template-parameter of integral or enumeration type, integral promotions (4.5) and integral conversions (4.7) are applied.

Either way, since 1 is both an int and implicitly convertible to a bool, your call is ambiguous.

2012-04-05 15:44
by Jerry Coffin
I see. Do you know if there's a specific reason why the rules are like this? I mean, is there some technical difficulty or something that would make it imnpracticable for compilers to apply the "exact-match-first/implicit-conversion-second" logic (used in function arguments) to template arguments - Malabarba 2012-04-05 16:05
No, I don't know for sure. My guess would be that it's mostly because the rules are already complex, and adding a set of rules for "ranking" like it does for overloading would make them even more so. I'm not sure, but I'd guess due to interaction with the other rules for templates, the ranking rules would end up at least a little different from those for overloads as well, so it wouldn't be just a matter of saying "the candidate functions will form an overload set to be resolved in accordance with §13.3. - Jerry Coffin 2012-04-05 16:13
Makes sense. Thanks. = - Malabarba 2012-04-05 16:27


5

Since this isn't a compiler bug but a language feature (see this answer), you have to find a work around.

Either you have to rename your functions or you can use this hack:

template <typename T> struct F;

template<> struct F<bool> {
  template <bool veracity>
  static int f(){return 1;}
};

template<> struct F<int> {
  template <int amount>
  static int f(){return 2;}
};

template <typename T, T value>
int f() { return F<T>::template f<value>(); }

// inside main():
std::cout << f<int,  2>() << '\n'; // prints 2
std::cout << f<bool, 2>() << '\n'; // prints 1
2012-04-05 15:52
by ipc
Ads