I have been experimenting with code derived from the "C++ Seasoning" presentation by Sean Parent, and have boiled my problem down to the following code:
#include <memory>
struct container {
struct concept {
virtual ~concept() {}
virtual void foo_() = 0;
};
template <class T> struct model : concept {
model (T x) : data_(x) {}
void foo_() {
foo(data_); // Line 13
}
T data_;
};
template <class T>
container(T x) : self_(new model<T>(x)) {} // Line 20
std::unique_ptr<concept> self_;
friend void foo(container &c) { c.self_->foo_(); }
};
void foo(int i) // Line 27
{
}
int main()
{
int i = 5;
container c(i); // Line 34
foo(c);
}
The problem I have is that this code that compiles with g++, and yet not with Clang.
Clang gives me the following error messages:
prio.cpp:13:13: error: call to function 'foo' that is neither visible in the
template definition nor found by argument-dependent lookup
foo(data_);
^
prio.cpp:20:32: note: in instantiation of member function
'container::model<int>::foo_' requested here
container(T x) : self_(new model<T>(x)) {}
^
prio.cpp:34:15: note: in instantiation of function template specialization
'container::container<int>' requested here
container c(i);
^
prio.cpp:27:6: note: 'foo' should be declared prior to the call site
void foo(int i)
^
My understanding is that overload resolution during templates occurs at the point of instantiation. In this case, that is line 34 (as marked above.) At this point, the global "foo" function is known. And yet, it appears not to resolve.
Note for posterity: This was with Clang built from trunk on 14/Jan/14
Is this a bug in Clang then, or with g++?
Gcc is wrong in this case, the code should not compile; but this is completely unrelated to the template. Friend declarations are particular in that they provide a declaration for a namespace level entity, but the declaration is not visible for normal lookup until a namespace declaration is also seen by the compiler.
Consider the simplified example:
struct X {
friend void f(int); // [1]
void g() { f(1); } // [2]
};
void h() { f(1); } // [3]
void f(int); // [4]
void i() { f(1); } // [5]
The friend declaration [1] inside the X class provides a declaration for a namespace level function f taking an int, but that declaration is not visible at namespace level until a namespace level declaration is present in [4]. Both [2] and [3] will fail to compile, although [5] will compile since at that point the compiler will have parsed the function declaration.
So how can the declaration in [1] be used by the compiler to resolve a call? In this particular case never. The friend declaration can only be found by argument dependent lookup, but ADL will only look inside X if one of the arguments to the function call is of type X. In this case, the function does not have any argument X, so lookup will never use the friend declaration for anything other than lifting the restrictions of access to the variables of X.
That is:
struct Y {
friend void f(int) {}
};
Without a latter namespace level declaration for f will declare and define a function that cannot be used anywhere in your program (lookup won't ever find it).
The simple workaround for your problem is to provide a declaration for the function at namespace level before the definition of the class:
#include <memory>
void foo(int);
struct container { // ...
Related
[ EDIT ] I changed the title from works to compiles since it turns out that it doesn't truly work after all (thanks #bogdan for the comments). I added code at the end of the post showing why and how.
The second part of the question still stands - is there a way to "fix" it? The crux of the matter is having a virtual function Observe in a base template<int N> class X be rerouted to a templated function Observe<N> in classes derived from X<N>, without requiring any supporting code in X.
For an example of how it can be done by requiring X to cooperate see this answer to the other question (which basically requires that Observe<N> be declared into the most derived class).
While looking at this other question Choosing which base class to override method of I found out that the following snippet compiles cleanly on vc++ 2015 (with /W4 /Za) and returns the expected output, yet fails to compile on gcc-5.1 and clang 3.7 (tried at ideone.com).
I am aware that specialization of template functions has many pitfalls, but I am still curious which letter of the C++ standard applies in this case, and - in the likely case that the code is not fully compliant - whether there is an easy way to "fix" it.
#include <iostream>
using std::cout;
using std::endl;
typedef int Parameter;
class Observer
{
public:
virtual void Observe(Parameter p) = 0;
};
class TaggedDispatch
{
public:
template<size_t Tag> void TObserve(Parameter p);
};
template<size_t Tag>
class TaggedObserver : virtual public TaggedDispatch, public Observer
{
public:
virtual void Observe(Parameter p) override
{ TObserve<Tag>(p); }
};
class Thing : public TaggedObserver<0>, TaggedObserver<11>
{ };
template<> void Thing::TObserve<0>(Parameter p)
{ cout << "Parent # 0, Parameter " << p << endl; }
template<> void Thing::TObserve<11>(Parameter p)
{ cout << "Parent # 11, Parameter " << p << endl; }
int main(int, char **)
{
Thing test;
test.TObserve<0>(101);
test.TObserve<11>(999);
return 0;
}
Output when compiled with vc++ 2015.
Parent # 0, Parameter 101
Parent # 11, Parameter 999
Compile errors fromgcc-5.1
prog.cpp:29:17: error: template-id 'TObserve<0>' for 'void Thing::TObserve(Parameter)' does not match any template declaration
template<> void Thing::TObserve<0>(Parameter p)
^
prog.cpp:32:17: error: template-id 'TObserve<11>' for 'void Thing::TObserve(Parameter)' does not match any template declaration
template<> void Thing::TObserve<11>(Parameter p)
Compile errors from clang 3.7.
prog.cpp:22:36: warning: 'override' keyword is a C++11 extension [-Wc++11-extensions]
virtual void Observe(Parameter p) override
^
prog.cpp:29:24: error: no function template matches function template specialization 'TObserve'
template<> void Thing::TObserve<0>(Parameter p)
^
prog.cpp:32:1: error: extraneous 'template<>' in declaration of variable 'TObserve'
template<> void Thing::TObserve<11>(Parameter p)
^~~~~~~~~~
prog.cpp:32:24: error: variable has incomplete type 'void'
template<> void Thing::TObserve<11>(Parameter p)
^
prog.cpp:32:32: error: expected ';' at end of declaration
template<> void Thing::TObserve<11>(Parameter p)
^
;
prog.cpp:32:32: error: expected unqualified-id
1 warning and 5 errors generated.
[ EDIT ] It doesn't truly work in vc++ 2015 after all. What appears to happen is that the compiler allows the void Thing::TObserve<0> definition, but internally maps it to void TaggedDispatch::TObserve<0>. This becomes obvious if adding another derived class e.g.
class Other : public TaggedObserver<0>
{ };
template<> void Other::TObserve<0>(Parameter p)
{ cout << "Parent # 00, Parameter " << p << endl; }
Then the vc++ 2015 compile fails with the error message:
error C2766: explicit specialization; 'void TaggedDispatch::TObserve<0>(Parameter)' has already been defined
MSVC is wrong to accept the code; Clang and GCC (and EDG) are right to reject it.
This case is similar to the one in this question, but it involves a different syntactic construct (and different code paths in the compilers, yielding different Standard conformance results, with only EDG being consistent).
In template<> void Thing::TObserve<0>(Parameter p), Thing::TObserve<0> is a declarator-id, with Thing:: being a nested-name-specifier. [8.3p1] says:
[...] When the declarator-id is qualified, the declaration shall refer
to a previously declared member of the class or namespace to which the
qualifier refers (or, in the case of a namespace, of an element of the
inline namespace set of that namespace (7.3.1)) or to a specialization
thereof; the member shall not merely have been introduced by a
using-declaration in the scope of the class or namespace nominated by
the nested-name-specifier of the declarator-id. [...]
So, you have to use template<> void TaggedDispatch::TObserve<0>. As noted in the question, using Thing:: could create the false impression that you can provide different explicit specializations of TObserve for different derived classes, which is not the case. There's only one TObserve member function template, the one declared in TaggedDispatch, and all such explicit specializations (and implicit or explicit instantiations, and partial specializations) are "attached" to that declaration.
One solution to make things work the way you expect is to declare an Observe member function template in each derived Thing-like class, possibly providing explicit specializations for relevant Tags if necessary, and let specializations of the template be automatically wired up to the corresponding Observer interface instance using CRTP:
#include <iostream>
#include <cstddef>
using Parameter = int;
struct Observer
{
virtual void Observe(Parameter p) = 0;
};
template<std::size_t Tag> struct TaggedObserver : Observer { };
template<class Derived, std::size_t Tag> struct CrtpObserver : TaggedObserver<Tag>
{
void Observe(Parameter p) override
{
static_cast<Derived*>(this)->template Observe<Tag>(p);
}
};
struct Thing : CrtpObserver<Thing, 0>, CrtpObserver<Thing, 1>
{
template<std::size_t N> void Observe(Parameter p);
};
template<> void Thing::Observe<0>(Parameter p)
{
std::cout << "Interface #0, Parameter " << p << '\n';
}
template<> void Thing::Observe<1>(Parameter p)
{
std::cout << "Interface #1, Parameter " << p << '\n';
}
int main()
{
Thing test;
TaggedObserver<0>* p0 = &test;
TaggedObserver<1>* p1 = &test;
p0->Observe(7);
p1->Observe(3);
}
This places the implementations of the Observer interface in Thing where they belong, while requiring minimal plumbing in each derived class - not much more than what you would have to do anyway if you could separately override each Observer::Observe directly.
This question is somewhat related to point of instantiation and name binding but not exactly. The question is about the standard and how it resolve lookup of symbols inside template definitions.
Consider this example, loosely based on ostream library:
// Output module
class Output {
public:
void operator<<(int);
void operator<<(double);
...
};
// Item module
class Item {
friend void operator<<(Output& obj, const Item& x) {
...
}
};
// Main program
int main() {
Output out;
Item item;
out << 3;
out << 2.0;
out << item;
}
In this example, the key points is that the output module is defined before any modules that use it and there is one module (Item module) that uses the output module to emit items.
This allow the base emit operators to be defined inside the Output class, but any module that define new classes and want to provide an emit method can do so by providing a friend function with two arguments. All fine so far.
Now, let's try to use the same idea without operator overloading and instead use plan member functions for the pre-defined emit functions for the base type and still allow class-specific emit functions to be defined as friend functions for the class:
class Output {
public:
template <class Type>
void emit(Type x) {
emit(*this, x);
}
void emit(int);
void emit(double);
};
class Item {
friend void emit(Output& obj, const Item& x) {
...
}
...
};
int main() {
Output out;
Item item;
out.emit(3);
out.emit(2.0);
out.emit(item);
}
Compared to the previous code, there is a template function added because it should not be necessary to have different calling conventions depending on the type. In other words, it should be possible to use the convention out.emit(...) regardless of what item is being emitted.
However, when compiling this (using GCC 4.8.4), we get the following error:
example.cc: In instantiation of ‘void Output::emit(Type) [with Type = Item]’:
example.cc:49:20: required from here
example.cc:33:9: error: no matching function for call to ‘Output::emit(Output&, Item&)’
emit(*this, x);
^
example.cc:33:9: note: candidates are:
example.cc:32:12: note: template<class Type> void Output::emit(Type)
void emit(Type x) {
^
example.cc:32:12: note: template argument deduction/substitution failed:
example.cc:33:9: note: candidate expects 1 argument, 2 provided
emit(*this, x);
^
example.cc:36:12: note: void Output::emit(int)
void emit(int) {
^
example.cc:36:12: note: candidate expects 1 argument, 2 provided
example.cc:37:12: note: void Output::emit(double)
void emit(double) {
^
example.cc:37:12: note: candidate expects 1 argument, 2 provided
In other words, the top-level emit function is never considered and instead only the member functions inside Output class is considered when resolving the name.
I assumed this was because the symbol emit was not a dependent name and hence was looked up at the point of definition (of the template) instead of point of instantiation, but section 14.6.2 §1 in the C++ Standard says (slightly edited):
[...] In an expression of the form:
postfix-expression ( expression-list opt )
where the postfix-expression is an identifier the identifier denotes a dependent name if and only if any of the expressions in expression-list is a type-dependent expression (14.6.2.2).
And further, in 14.6.2.2 ("Type-dependent expressions") §2 it says:
this is type-dependent if the class type of the enclosing member function is dependent
Which, AIUI, is the case here.
So, the questions are:
Why doesn't the lookup consider the top-level version of emit in the name resolution here?
Is it possible to make the second example work in the same way as the first one so that the template member function definition will consider both member functions or namespace scope functions at the point of instantiation?
Update: Changed the title of the post to be more accurate and did a slight edit of the quotes from the standard.
As Johannes points out, if a member function is found ADL is not invoked and ADL is necessary to find the friend declaration of Item.
So, to answer the first question, Section 3.4.2 §2 in the C++ standard (C++03 version) says:
If the ordinary unqualified lookup of the name finds the declaration of a class member function, the associated namespaces and classes are not considered. [...]
To answer the second question, here is the fixed sample code:
namespace emitter {
class Output;
template <class Type>
void emit(Output& out, const Type& t) {
emit(out, t);
}
class Output {
public:
template <class Type>
void emit(Type x) {
using emitter::emit;
emit(*this, x);
}
void emit(int);
void emit(double);
};
}
class Item {
friend void emit(emitter::Output& obj, const Item& x) {
...
}
};
I am, however, still struggling to find the paragraph that clarifies why the using declaration solves the issue. The closest I can find right now is 7.3.3 §13:
For the purpose of overload resolution, the functions which are introduced by a using-declaration into a derived class will be treated as through they were members of the derived class.
But this refers to using B::f in a class D derived from B, so not a perfect match.
I don't understand the need for the static_cast in the following C++ code snippet (tested with GCC-4.7):
#include <cstdio>
class Interface
{
public:
virtual void g(class C* intf) = 0;
virtual ~Interface() {}
};
class C
{
public:
void f(int& value)
{
printf("%d\n", value);
}
void f(Interface* i)
{
i->g(this);
}
template <typename T>
void f(T& t);
//void f(class Implementation& i);
};
class Implementation : public Interface
{
public:
Implementation(int value_) : value(value_) {}
void g(C* intf)
{
intf->f(value);
}
private:
int value;
};
int main()
{
C a;
Implementation* b = new Implementation(1);
//a.f(b); // This won't work: undefined reference to `void C::f<Implementation*>(Implementation*&)'
a.f(static_cast<Interface*>(b));
delete b;
return 0;
}
If I omit the static_cast, I get a linker error because it wants to use:
template <typename T>
void f(T& t);
instead of:
void f(Interface* i);
On the other hand, if I replace the templated method with the following (commented out in the above snippet):
void f(class Implementation& i);
then I don't get errors and I can see that the "correct" method is called at run-time (that is:
void f(Interface* i);
).
Why does the declaration of the template method affect name lookup?
Many thanks in advance,
When performing overload resolution for a.f(b), the compiler notes two facts:
First, You are trying to call f with an lvalue of type Implementation*.
Second, three functions are in the overload set: C::f(int&) and C::f(Interface*) and C::f<Implementation*>(Implementation*&). Note that the template is included since its template parameter could be deduced from the argument it is being called with.
Now the compiler starts to check which function fits "best":
C::f(int&) cannot be called with this argument at all.
C::f(Interface*) can be called, but requires one standard conversion (pointer to derived -> pointer to base)
C::f<Implementation*>(Implementation*&) can be called without any conversions
Thus, the template quite simply fits best. However, as you did not define an implementation for the template, the linker later on bugs out with the error message that it cannot find the function you are trying to call.
The situation is that some member function bar::Bar::frobnicate wants to utilize ADL to find a function from some unknown namespace, within a function that has an identical name. However, it only finds its own name.
Testcase
(Note that in reality, Bar is a Foo-agnostic template; this is just the reproducible, minimal testcase)
namespace foo {
struct Foo {};
void frobnicate(Foo const &) {}
}
namespace bar {
struct Bar {
void frobnicate() {
foo::Foo foo;
frobnicate(foo); // <-- error
}
};
}
int main () {
bar::Bar x;
x.frobnicate();
frobnicate(foo::Foo());
}
Results in:
test.cc: In member function ‘void bar::Bar::frobnicate()’:
test.cc:10:31: error: no matching function for call to ‘bar::Bar::frobnicate(foo::Foo&)’
test.cc:10:31: note: candidate is:
test.cc:8:18: note: void bar::Bar::frobnicate()
test.cc:8:18: note: candidate expects 0 arguments, 1 provided
Standard
I understand that this is correct compiler behaviour:
3.4.1 Unqualified name lookup [basic.lookup.unqual]
(...) name lookup ends as soon as a declaration is found for the name (...)
and only after unqualified lookup failed, argument dependent lookup comes into play:
3.4.2 Argument-dependent name lookup [basic.lookup.argdep]
When the postfix-expression in a function call (5.2.2) is an unqualified-id, other namespaces not considered
during the usual unqualified lookup (3.4.1) may be searched
Workaround
My current workaround is to introduce a special traits class that does not define the clashing name itself:
struct BarTraits {
void frobnicate_(foo::Foo const &b) {
frobnicate(b);
}
};
or this ligher version:
void frobnicate_(foo::Foo const &c) { frobnicate(c); }
Question
Are there better alternatives than introducing such traits classes?
Explicitly qualifying the call as foo::frobnicate(foo) is not an option here, because (as mentioned) the Bar class is a template upon Foo in reality and should not only work for types in the foo namespace.
As you found out yourself, adding a member function frobnicate to the class interface of Bar (or Bar<T> in the template case), will prevent ADL from finding foo::frobnicate.
The easiest -and in this case idiomatic- way to add frobnicate functionality to a class Bar (or to a class template Bar<T>) is to add a non-member function frobnicate(Bar) (or function template frobnicate(Bar<T>)) to the namespace bar
namespace foo {
struct Foo {};
void frobnicate(Foo const &) {}
}
namespace bar {
template<class T>
struct Bar {
T t;
};
template<class T>
void frobnicate(Bar<T> const& b)
{
frobnicate(b.t);
}
}
int main () {
bar::Bar<foo::Foo> x;
frobnicate(x);
frobnicate(foo::Foo());
}
If you insist on having a member function, you will have to rename it to something like do_frobnicate(). I would not use type traits tricks to get the same behavior as it is an indirect approach, and makes the class interfaces much harder to understand (remember Stroustrup's motto: "represent your ideas directly in code").
you can use this trick
namespace dummy { void your_func(may be some parameteres); }
struct bar {
void member() {
using dummy::your_func; // now your call will find that and ADL will kick in
I just do it with a proxy function
namespace utils
{
int lookup_adl(int arg)
{
return lookup(arg);// ADL search
}
struct Foo
{
int lookup(int arg) { return ::utils::lookup_adl(arg);}
};
}
Why does the following code prints different results on different compilers?
#include <iostream>
void foo() { std::cout << "::foo() \n"; }
namespace Foo
{
struct Bar
{
friend void foo() { std::cout << "Bar::foo() \n"; }
void bar() { foo(); }
void baz();
};
void Bar::baz() { foo(); }
}
int main()
{
Foo::Bar instance;
instance.bar();
instance.baz();
}
Output
gcc 4.7.2
::foo()
::foo()
MSVC-10.0
Bar::foo()
Bar::foo()
MSVC-11.0
error C3861: 'foo': identifier not found
error C3861: 'foo': identifier not found
Who is right? And why is it so?
I think gcc is right:
7.3.1.2/3 in C++11:
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 unqualified lookup (3.4.1) or by qualified
lookup (3.4.3) until a matching declaration is provided in that
namespace scope (either before or after the class definition
C++03 has similar language in the same place.
I'm not sure why MSVC-11 fails to find ::foo, but I suppose you could read this text to mean that the name foo can't be looked up at all. I think the intended meaning is that the name in the innermost enclosing namespace can't be found, but the identically-spelled name in the outer scope can. But if Microsoft wants to argue the intended meaning I'm not the person they'd argue it with.
MSVC-10 is wrong, because it found a name that the standard specifically says is not found. So the explanation for the MSVC-11 behavior might be as simple as "it was reported as a bug in 10, they tried to fix it and went too far".
Anyway, the fix is to introduce a declaration of foo in namespace Foo:
namespace Foo
{
void foo(); // this is a matching declaration
struct Bar
{
friend void foo() { std::cout << "Bar::foo() \n"; }
void bar() { foo(); }
void baz();
};
void Bar::baz() { foo(); }
}
This makes gcc find the friend function. I haven't tested on any version of MSVC.