As described here C++11 style SFINAE and function visibility on template instantiation class member functions overshadow free functions. Using a fully qualified name usually works, however I am having a hard time with friend functions of other classes which are declared in-line. Consider the following example:
namespace N {
struct C {
friend int f(const C& c) {
return 1;
}
friend int g(const C& c) {
return 2;
}
};
struct D {
void f() {
g(C{}); // ADL finds this
::N::f(C{}); // not found dispite full qualification
}
};
}
I think I understand what the problem is, as described here What's the scope of inline friend functions? inline friend function are usually found using ADL and not really visible in the enclosing namespace.
So my question is how should I change my code to make this work (aside from renaming one of the f's)?
It's because of the friendliness:
[C++11: 7.3.1.2/3]: If a friend declaration in a non-local class first declares a class or function the friend class or function is a member of the innermost enclosing namespace. The name of the friend is not found by simple name lookup until a matching declaration is provided in that namespace scope [...]. If a friend function is called, its name may be found by the name lookup that considers function from namespaces and classes associated with the types of the function arguments (3.4.2) [i.e. ADL].
The fix is to simply provide that declaration:
namespace N {
struct C {
friend int f(const C& c) {
return 1;
}
friend int g(const C& c) {
return 2;
}
};
int f(const C& c);
int g(const C& c);
struct D {
void f() {
g(C{});
::N::f(C{});
}
};
}
(live demo)
I'm just curious to know why this small piece of code compiles correctly (and without warnings) in Visual Studio. Maybe the result is the same with GCC and Clang, but unfortunately I can't test them now.
struct T {
int t;
T() : t(0) {}
};
int main() {
T(i_do_not_exist);
return 0;
}
T(i_do_not_exist); is an object declaration with the same meaning as T i_do_not_exist;.
N4567 § 6.8[stmt.ambig]p1
There is an ambiguity in the grammar involving expression-statements and declarations: An expression-statement with a function-style explicit type conversion (5.2.3) as its leftmost subexpression can be indistinguishable from a declaration where the first declarator starts with a (. In those cases the statement is a declaration.
§ 8.3[dcl.meaning]p6
In a declaration T D where D has the form
( D1 )
the type of the contained declarator-id is the same as that of the contained declarator-id in the declaration
T D1
Parentheses do not alter the type of the embedded declarator-id, but they can alter the binding of complex declarators.
Because it defines a variable of type T:
http://coliru.stacked-crooked.com/a/d420870b1a6490d7
#include <iostream>
struct T {
int t;
T() : t(0) {}
};
int main() {
T(i_do_not_exist);
i_do_not_exist.t = 120;
std::cout << i_do_not_exist.t;
return 0;
}
The above example looks silly, but this syntax is allowed for a reason.
A better example is:
int func1();
namespace A
{
void func1(int);
struct X {
friend int (::func1)();
};
}
Probably other examples could be found.
clang doesn't compile the third call to typeid below (see live example). But I can't see anything in §5.2.8 that disallows this, specially when we consider that the expression B::f is not a glvalue of polymorphic class type (see paragraph 3). Also, according to this paragraph the expression B::f is an unevaluated operand, and as such, the call typeid(B::f) should compile. Note that GCC doesn't compile any of the calls to typeid below:
#include <iostream>
#include <typeinfo>
struct A{ int i; };
struct B{ int i; void f(); };
int main()
{
std::cout << typeid(A::i).name() << '\n';
std::cout << typeid(B::i).name() << '\n';
std::cout << typeid(B::f).name() << '\n';
}
As far as I can tell clang is correct, using a non static member is only valid in an unevaluated context if it is a data member. So it looks like gcc is incorrect for the first two cases, but gcc works correctly in the case of sizeof and decltype which also have unevaluated operands.
From the draft C++11 standard section 5.1.1 [expr.prim.general]:
An id-expression that denotes a non-static data member or non-static
member function of a class can only be used:
and includes the following bullet:
if that id-expression denotes a non-static data member and it appears
in an unevaluated operand. [ Example:
struct S {
int m;
};
int i = sizeof(S::m); // OK
int j = sizeof(S::m + 42); // OK
—end example ]
The rest of the bullets do not apply, they are as follows:
as part of a class member access (5.2.5) in which the object expression refers to the member’s class61 or a class derived from that
class, or
to form a pointer to member (5.3.1), or
in a mem-initializer for a constructor for that class or for a class derived from that class (12.6.2), or
in a brace-or-equal-initializer for a non-static data member of that class or of a class derived from that class (12.6.2), or
We know that operand is unevaluated from section 5.2.8 which says:
When typeid is applied to an expression other than a glvalue of a
polymorphic class type, [...] The expression is an unevaluated operand
(Clause 5).
We can see from the grammar that an id-expression is either an unqualified-id or a qualified-id:
id-expression:
unqualified-id
qualified-id
Update
Filed a gcc bug report: typeid does not allow an id-expression that denotes a non-static data member.
typeid(A::i).name() doesn't quite do what I thought it would do. I expected it to be a pointer-to-member, but it's actually just an int.
To see this, run this code:
#include <iostream>
struct A{ int i; };
struct B{ int i; void f(void); };
template<typename T>
void what_is_my_type() {
std:: cout << __PRETTY_FUNCTION__ << std:: endl;
}
int main()
{
what_is_my_type<decltype(&A::i)>(); // "void what_is_my_type() [T = int A::*]"
what_is_my_type<decltype(&B::i)>(); // "void what_is_my_type() [T = int B::*]"
what_is_my_type<decltype(&B::f)>(); // "void what_is_my_type() [T = void (B::*)()]"
what_is_my_type<decltype(A::i)>(); // "void what_is_my_type() [T = int]"
what_is_my_type<decltype(B::i)>(); // "void what_is_my_type() [T = int]"
// what_is_my_type<decltype(B::f)>(); // doesn't compile
}
I've put the output in a comment after each call.
The first three calls work as expected - all three work and the type information includes the type of the struct (A or B) as well as the type of member.
The last three are different though. The final one doesn't even compile, and the first two simply print int. I think this is a clue as to what is wrong. It is possible, given a particular A or B, to take the address of that particular member:
A a;
int * x = &(a.i);
*x = 32;
but it is not possible (or even meaningful?) to do this:
B b;
??? y = &(a.f); // what does this even mean?
Finally, to emphasize that this is not about pointers, consider this:
A a;
B b;
int x = a.i;
int y = b.i;
??? z = b.f; // what would this mean? What's its type?
There are 3 examples:
I.
int foo(int i){ return 0; }
namespace A
{
int foo();
int a = foo(5);//Error: too many argument to function int a::foo()
}
II.
namespace A
{
int foo(int i){ return 0; }
int foo(){ return 1; }
int a = foo(5);//OK, Call A::foo(int)
}
III
namespace A
{
int foo(){ return 1; }
int foo(int i){ return 0; }
int a = foo(5);//OK, Call A::foo(int)
}
What exactly rules used to determine the set of candidate functon? I thought that (3.4.1/1)
name lookup ends as soon as a declaration is found for the name.
It is unclear what declaration (int foo(int) or int foo()) will be found first in the cases II and III?
From §13-1 Overloading,
When two or more different declarations are specified for a single name in the same scope, that name is said
to be overloaded. By extension, two declarations in the same scope that declare the same name but with
different types are called overloaded declarations. Only function and function template declarations can be
overloaded; variable and type declarations cannot be overloaded.
Since you have overloaded function declarations in the same namespace, unqualified name lookup finds matches the set of functions and stops. (I admit the standardese seem a bit incorrect here since it says "as soon as a declaration is found for the name".)
So for II and III, unqualified name lookup finds the same set of overloaded functions.
Extending III a bit further,
int foo(int i) { return 42; }
namespace A {
int foo() { return 1; }
int foo(int i) { return 0; }
int a = foo(5); // OK, Call A::foo(int)
}
Now, it may seem as ::foo(int) and A::foo(int) might be ambiguous but it's not because unqualified name lookup stops after finding A::foo() and A::foo(int). Then it's up to overload resolution to pick the best viable function.
Function overloading only works if the functions are in the same namespace. That is, the name is looked up first by namespace, then by the function signature. In case I, there is a function named foo inside of the A namespace, so it tries to call that, but there is no definition of foo in that namespace which accepts an integer parameter.
In any case, you can call the global foo function as follows:
int a = ::foo(5);
The double colon, with no namespace prefix accesses the global namespace.
Inside a C++ template function foo(), a call to ::bar(TT*) gives the following error under gcc 4.4.3:
g++ -o hello.o -c -g hello.cpp
hello.cpp: In function 'void foo(std::vector<TT*, std::allocator<TT*> >&)':
hello.cpp:8: error: '::bar' has not been declared
Here's the offending code:
// hello.cpp
#include <vector>
template<typename TT> void foo(std::vector<TT*> &vec)
{
TT *tt;
::bar(tt);
vec.push_back(tt);
}
class Blah
{
};
void bar(Blah *&)
{
}
int main(int argc, char *argv[])
{
std::vector<Blah*> vec;
foo(vec);
return 0;
}
C++ distinguishes between symbols that are dependent on the template parameter (TT, here) and those symbols that are independent and can be evaluated immediately.
Clearly, the compiler thinks my ::bar(TT*) call is independent and tries to resolve it immediately. Just as clearly, that function call is dependent on TT because the function call takes a parameter of type TT*, so the compiler should wait until the foo(vec) instantiation to resolve ::bar(TT*).
Is this a gcc bug or am I missing something subtle about C++ templates?
EDIT: here's a slightly more complicated example with two versions of ::bar() to clarify that declaration order is not the issue with my problem. When parsing the template, the compiler has no way of knowing if main() down below is going to instantiate the template function with TT=Blah or with TT=Argh. Therefore the compiler should not be giving an error until line 35 line 28 at the earliest (if ever). But the error is given for line 8 line 16.
EDIT #2: improved this example.
EDIT #3: added corrections to this example to make it work as desired. The bar(tt) now correctly refers to bar(Blah*). Rationale given below. (Thanks everyone).
// hello.cpp
#include <vector>
class XX {};
void bar(XX*) {}
class CC {
public:
void bar();
void bar(int *);
void bar(float *);
template<typename TT> static void foo(std::vector<TT*> &vec);
};
template<typename TT>
void CC::foo(std::vector<TT*> &vec) {
using ::bar;
TT *tt;
bar(tt);
vec.push_back(tt);
}
class Argh {};
void bar(Argh *&aa) { aa = new Argh; }
class Blah {};
void bar(Blah *&bb) { bb = new Blah; }
int main(int argc, char *argv[]) {
std::vector<Blah*> vec;
CC::foo(vec);
return 0;
}
Nobody has yet pointed out any part of the current Standard that says I can't.
C++03 does not make the name ::bar dependent. Dependency happens for type names by dependent types, and for non-type names by dependent expressions that are either type or value dependent. If a name is looked up in a dependent type, it becomes a type-dependent id-expression (14.6.2.2/3 last bullet), and its lookup is delayed until instantiation. The name ::bar is no such dependent expression. If you were to call bar(tt), a special rule of C++03 at 14.2.6 says
In an expression of the form:
postfix-expression ( expression-listopt )
where the postfix-expression is an identifier, the identifier denotes a dependent name if and only if any of the expressions in the expression-list is a type-dependent expression (14.6.2.2).
So you need to remove the :: in order to make it an identifier and to make it dependent by this special rule.
The reason I can't remove the :: is that in my real code, the template function foo is a member function of class CC, and there exist a family of overloaded member functions CC::bar(...), meaning I need to qualify ::bar(TT*) to avoid defaulting to CC::bar(...). That's what :: exists for, I'm surprised if the Standard says I can't use :: here
The proper way to solve it is to introduce a using declaration into the local scope of your function.
namespace dummies { void f(); }
template<typename T>
struct S {
void f();
void g() {
using dummies::f; // without it, it won't work
f(T()); // with ::f, it won't work
}
};
struct A { };
void f(A) { } // <- will find this
int main() {
S<A> a;
a.g();
}
ADL will not do anything if ordinary lookup finds a class member function. Therefor, you introduce a using declaration, so ordinary lookup doesn't find a class member function, and ADL can advance the declarations visible when instantiating.
But this seems to disagree with you: Stroustrup TC++PL Sp Ed, Section C.13.8.1, Dependent Names: "Basically, the name of a function called is dependent if it is obviously dependent by looking at its arguments or at its formal parameters"
Stroustrup's book is also written for people who possibly don't know C++ yet. It won't try to cover all rules with 100% accuracy, as is normal for these books. The gory details are left for ISO Standard readers.
Also, the formal parameters of a function have nothing to do with whether a function call is dependent or not. In the IS, only actual arguments define dependency of a function name. This was different in an old draft from 1996, which had the notion of implicit and explicit dependency. Implicitly dependency was defined as
A name implicitly depends on a template-argument if it is a function
name used in a function call and the function call would have a dif-
ferent resolution or no resolution if a type, template, or enumerator
mentioned in the template-argument were missing from the program.
[...]
[Example: some calls that depend on a template-argument type T are:
The function called has a parameter that depends on T according to
the type deduction rules (temp.deduct). For example, f(T),
f(Array), and f(const T*).
The type of the actual argument depends on T. For example, f(T(1)),
f(t), f(g(t)), and f(&t) assuming that t has the type T.
A practical example is also given
This ill-formed template instantiation uses a function that does not
depend on a template-argument:
template<class T> class Z {
public:
void f() const
{
g(1); // g() not found in Z's context.
// Look again at point of instantiation
}
};
void g(int);
void h(const Z<Horse>& x)
{
x.f(); // error: g(int) called by g(1) does not depend
// on template-argument ``Horse''
}
The call x.f() gives rise to the specialization:
void Z<Horse>::f() { g(1); }
The call g(1) would call g(int), but since that call does not depend
on the template-argument Horse and because g(int) was not in scope at
the point of the definition of the template, the call x.f() is ill-
formed.
On the other hand:
void h(const Z<int>& y)
{
y.f(); // fine: g(int) called by g(1) depends
// on template-argument ``int''
}
Here, the call y.f() gives rise to the specialization:
void Z<int>::f() { g(1); }
The call g(1) calls g(int), and since that call depends on the tem-
plate-argument int, the call y.f() is acceptable even though g(int)
wasn't in scope at the point of the template definition. ]
These things are left to history, and even the last traces from it are disappearing slowly, albeit not actively driven (n3126 for instance gets rid of "explicitly depends" at [temp.names]/p4 as a side-effect of another change, because the distinction between "explicitly depends" and "implicitly depends" has never existed in the IS).
From section 14.7.2 of the C++ spec:
In an expression of the form:
postfix-expression ( expression-listopt )
where the postfix-expression is an unqualified-id but not a template-id , the unqualified-id denotes a dependent
name if and only if any of the expressions in the expression-list is a type-dependent expression (14.7.2.2).
since ::b is not an unqualified id, it is not a dependent name. If you remove the ::, it is an unqualified name and so is a dependent name. For a non-dependent name, the lookup occurs at the point of the template declaration, not the instantiation, and at that point there is no global declaration of bar visible, so you get an error.
This ugliness works with Intel C++ 11.0 and perhaps illuminates the compiler's point of view:
#include <vector>
#include <iostream>
// *********************
// forward declare in the global namespace a family of functions named bar
// taking some argument whose type is still a matter of speculation
// at this point
template<class T>
void bar(T x);
// *********************
template<typename TT>
void foo(std::vector<TT*> &vec)
{
TT *tt;
::bar(tt);
vec.push_back(tt);
}
class Blah
{
public:
};
void bar(Blah *x)
{
// I like output in my examples so I added this
std::cout << "Yoo hoo!" << std::endl;
}
// **********************
// Specialize bar<Blah*>
template<>
inline
void bar<Blah*>(Blah *x) { ::bar(x); }
// **********************
int main(int, char *)
{
std::vector<Blah*> vec;
foo(vec);
return 0;
}
This should work, your problem is the declaration order:
// hello.cpp
#include <vector>
class Blah
{
public:
};
void bar(Blah *&)
{ }
template<typename TT> void foo(std::vector<TT*> &vec)
{
TT *tt;
::bar(tt);
vec.push_back(tt);
}
int main(int argc, char *argv[])
{
std::vector<Blah*> vec;
foo(vec);
return 0;
}
A dependent name still requires a function declaration. Any function declaration with that name will do, but there must be something. How else would the compiler disambiguate an overloaded function call from, say, a misspelled functor object? In other words, finding some function of that name, thus verifying that overloading on that name is possible, instigates the overload resolution process in qualified (or unqualified) name lookup.
// hello.cpp
#include <vector>
void bar(); // Comeau bails without this.
template<typename TT> void foo(std::vector<TT*> &vec)
{
TT *tt;
::bar(tt);
vec.push_back(tt);
}
class Blah
{
};
void bar(Blah *&)
{
}
int main(int argc, char *argv[])
{
std::vector<Blah*> vec;
//foo(vec); - instanting it is certainly an error!
return 0;
}
Your code works fine on VS2005. so it indeed seems like a bug in gcc. (I don't know what the specs say about this, maybe someone will come along and post it.)
As for gcc, I also tried defining a different overload of bar before foo, so that the symbol bar is at least defined:
void bar(float *) {
}
template<typename TT> void foo(std::vector<TT*> &vec)
{
TT *tt;
::bar(tt);
vec.push_back(tt);
}
void bar(int *) {
}
int main(int argc, char *argv[])
{
std::vector<int*> vec;
foo(vec);
return 0;
}
but gcc is still totally blind to the int * overload:
error: cannot convert int* to float* for argument 1 to void bar(float*)
It seems gcc will only use those functions that are defined before the template itself.
However, if you remove the explicit :: specifier and make it just bar(tt), it seems to work fine. Chris Dodd's answer seems satisfactory in explaining why this is so.