Reputation: 259
The following won't compile:
enum E {A,B,C};
template<E m>
void foo(E m) {}
int main() {
foo(A);
return 0;
}
The errors I get are:
I don't understand what exactly is wrong here. Why can't the compiler deduce the template parameter from the function argument?
What do I need to do to make this work?
Upvotes: 2
Views: 753
Reputation: 259
It has finally dawned on me why this does not compile. Although in my particular case the function argument is a compile-time constant (an enum member), in general a function argument is run-time dependent. The template value must be a compile-time constant, so function argument values are not permissible for template value deduction. If the mechanism for enforcing this is name-hiding, then I think that is incidental. The conclusion is that whereas templated function types may be deduced from function argument type, template values are not deducible.
Upvotes: 0
Reputation: 56863
If you want a run-time argument, use:
void foo(E m) {}
Which has a value m
of type E
. (note: no template<E m>
required)
If you want a compile-time argument, use:
template<E m>
void foo() {}
and call:
foo<A>();
Or if you want foo
to work for all enumeration types:
template<typename E>
void foo(E m) {}
And probably check for enums with
static_assert(std::is_enum<E>::value, "E is not an enumeration");
in the function body. (You can also use SFINAE to remove foo
from an overload set if needed, ask if you need help with that)
Update: Explaining your original code and what is wrong with it:
template<E m> void foo(E m) {}
// ^^^ (1) ^^^ (2)
(1) is a compile-time argument m
of type E
, (2) is a run-time argument also called m
and also of type E
. Since it has the same name, the second argument hides the first one. Using the name m
in your function will only access the second argument and you can not access the first one. Now consider:
template<E m1> void foo(E m2) {}
Now you can access the arguments under different names, i.e., m1
and m2
. If you call the function like this:
foo<A>(B);
then m1
is A
and m2
is B
. And still both are of the same fixed type E
. They are independent parameters and the value of the run-time parameter will not be used for the compile-time parameter.
Depending on which kind or argument you need (compile-time or run-time), you simply leave out the one you don't need and you end up with one of the above implementations.
It's not 100% clear to me where your real problem is, which is not untypical for beginners as it is admittedly hard to describe a problem you don't really understand, but make sure you start by understanding the difference between the compile-time and the run-time parameters and how they can be used.
Upvotes: 6
Reputation: 22680
I guess you wanted to write:
enum E {A,B,C};
template<typename T>
void foo(T m) {}
int main() {
foo(A);
return 0;
}
Upvotes: 2