Forcing name lookup to consider namespace scope - c++

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.

Related

C++ compiler does not check if a method exists in template class

I came across with the following program in C++:
template <class T>
class Val {
protected:
T x0, x;
public:
Val(T t = 1) : x0(t), x(1) {}
T val() { return x; }
void promote() { this->promote_value(); }
};
For some reason Val<int>(4).val(); works fine even though there is no method promote_value(). I tried to remove the templates:
class OtherVal {
protected:
int x0, x;
public:
OtherVal (int t = 1) : x0(t), x(1) {}
int val() { return x; }
void promote() { this->promote_value(); }
};
But now I get an error:
error: ‘class OtherVal’ has no member named ‘promote_value’; did you mean ‘promote’?
Why does C++ behave like this?
Template class methods are not instantiated until they are used. Once you try calling promote() or even get its address like this &Val<int>::promote then you'll get an error.
From the C++ standard:
§ 17.8.1.10 An implementation shall not implicitly instantiate a function
template, a variable template, a member template, a non-virtual member
function, a member class, a static data member of a class template,
or a substatement of a constexpr if statement (9.4.1), unless such
instantiation is required.
Templates have always worked this way, principally to facilitate their use.
Because Val<int>(4).val(); doesn't call promote, that function is not compiled for your particular instantiation of that template so the compiler does not issue a diagnostic.
Many metaprogramming techniques depend on this behaviour.

MSVC is happy with this code but GCC isn't so keen

This code compiles in MSVC (19.00.23918) but GCC doesn't like it unless I use this-> access to member operator when I call Detach_Internal().
Is GCC catching a potential bug here that MSVC isn't? As a general rule is it a better idea to use this-> at all times when referencing functions in base classes?
Note GCC will compile it with -fpermissive.
#include <memory>
namespace Events
{
template<typename T>
class EventBase
{
protected:
void Detach_Internal(std::weak_ptr<void> const & p)
{
}
};
template<typename T>
class Event : public EventBase<T>
{
public:
void Detach(std::weak_ptr<void> const & p)
{
Detach_Internal(p);
}
};
}
int main(void)
{
auto event = std::make_unique<Events::Event<void()>>();
}
33:30: error: there are no arguments to 'Detach_Internal' that depend on a template parameter, so a declaration of 'Detach_Internal' must be available [-fpermissive]
Is GCC catching a potential bug here that VS isn't? As a general rule is it a better idea to use this-> at all times when referencing functions in base classes?
GCC is correct. You should add this-> when referring names in dependent base class (i.e. EventBase<T>, which depends on template parameter T).
Otherwise as a nondependent name, Detach_Internal won't be looked up in dependent base class EventBase<T>.
To solve the issue you can make the name Detach_Internal dependent, then it will be looked up at the time of instantiation, at that time the exact base class template specialization is fixed. e.g.
this->Detach_Internal(p);
EventBase<T>::Detach_Internal(p);
using EventBase<T>::Detach_Internal;
Detach_Internal(p);

case of template member function specialization that compiles on msvc, not others

[ 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.

Clang does not find function instantiated after function definition in template context

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 { // ...

ADL in case of equal-named member function

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);}
};
}