In question 15 of the 2012 ACCU C++ Pub quiz , I am stumped by the result.
#include <iostream>
template<typename T> void P(T x) { std::cout << x; }
void foo(char a) { // foo 1
P(3);
P(a);
}
template <typename... A> // foo 2
void foo(int a, A... args) {
foo(args...);
P(a);
}
template <typename... A>
void foo(char a, A... args) { // foo 3
P(a);
foo(args...);
}
int main()
{
foo('1','2',48,'4','5');
}
I reasoned that it would call foo 3
, foo 3
, foo 2
, foo 3
, foo 1
, and thus give an output of 1243548
. The actual output is 12355248
, and confirmed in my debugger as following foo 3
, foo 3
, foo 2
, foo 2
, foo 1
. I cannot work out why the fourth foo
call is going to foo 2
not foo 3
.
For reference, I compiled with gcc 4.8.1 g++ -g -Wall -std=c++11 -Weffc++ -Wextra -O0 /tmp/foo.cpp -o /tmp/foo
and got no warnings at all.
Edit: I've just tried it on Visual Studio Express 2013, and it gives 1243548
, also with no warnings.
Is this a compiler bug in GCC / VS, or one of those awkward unspecified behaviour parts of the specification?
It looks like its the order of declaration. If you forward declare the relevant overload of foo above foo 2 then you will see the result you expected, ie put this above foo 2:
template <typename... A>
void foo(char a, A... args);
The relevant portion of the standard is in 3.4.1.4:
A name used in global scope, outside of any function, class or user-declared namespace, shall be declared before its use in global scope.
And in 14.6.4.1 Dependent name resolution:
In resolving dependent names, names from the following sources are considered:
— Declarations that are visible at the point of definition of the template.
— Declarations from namespaces associated with the types of the function arguments both from the instantiation context (14.6.4.1) and from the definition context.
As args
is a dependent type, name resolution only considers names visible as the point of definition of the template. foo 3
has not been declared by this point so can't be considered in overload resolution. On that basis Visual Studio appears to be wrong in allowing the use of foo 3
.
foo 2
不能调用foo 3
因为foo 3
不在foo 2
范围内。
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.