C++ Function Template instantiaion with implicit parameters
-
03-06-2021 - |
题
I can't figure out why the following code compiles fine:
#include <iostream>
void bar(int x) {
std::cout << "int " << x << std::endl;
}
void bar(double x) {
std::cout << "double " << x << std::endl;
}
template <typename A, typename B> // Note the order of A and B.
void foo(B x) {
bar((A)x);
}
int main() {
int x = 1;
double y = 2;
foo<int>(x); // Compiles OK.
foo<double>(y); // Compiles OK.
return 0;
}
But if I switch the order of A
and B
as below, then it won't compile:
#include <iostream>
void bar(int x) {
std::cout << "int " << x << std::endl;
}
void bar(double x) {
std::cout << "double " << x << std::endl;
}
template <typename B, typename A> // Order of A and B are switched.
void foo(B x) {
bar((A)x);
}
int main() {
int x = 1;
double y = 2;
foo<int>(x); // error: no matching function for call to ‘foo(int&)’
foo<double>(y); // error: no matching function for call to ‘foo(double&)’
return 0;
}
EDIT: Ad-hoc explanations are welcome, but would be better if someone can point out exact what the spec. says. Thanks!
解决方案
In the first one, the compiler knows that A
is int
because you specifically tell it so with foo<int>
, and it knows that B
is also int
because of the parameter that you pass it. So both A
and B
are known or can be deduced (you could say: A
is supplied, B
is implied).
However, in the second one, since B
comes first and A
doesn't appear in the parameter list, the compiler can't tell what A
is and gives you an error. You're explicitly telling it what B
is with foo<int>
, and then the parameter you pass is also a B
which, at the call, is an int
which agrees with your previous explicit definition of B
, but no mention is made of A
, implicitly or explicitly, so the compiler must stop and error.
You don't really need the standard for this, it's just common sense. What on earth would A
be in the second one?
Thanks for asking this question though, because I didn't realise you could explicitly specify some parameters and implicitly specify others in the parameter list before this.