gcc template resolution and namespaces - c++

Warning, C++ hating ahead...
I have seen here slightly different variations of this issue, here is my take
namespace space {
}
template <typename T> struct C
{
void foo() {
using namespace space;
bar(t);
}
T t;
};
class A {
};
namespace space {
void bar(const A& a){
}
}
int main()
{
C<A> c;
c.foo();
return 0;
}
if bar is not inside a namespace, everything compiles ok. Putting a namespace breaks compilation with gcc. What is more interesting - gcc finds the function, but just don't feel like using it:
ConsoleApplication1.cpp: In instantiation of 'void C<T>::foo() [with T = A]':
ConsoleApplication1.cpp:26:10: required from here
ConsoleApplication1.cpp:8:8: error: 'bar' was not declared in this scope, and no declarations were found by argument-dependent lookup at the point
instantiation [-fpermissive]
bar(t);
^
ConsoleApplication1.cpp:18:6: note: 'void space::bar(const A&)' declared here, later in the translation unit
void bar(const A& a){
Is there any sane reason for this behaviour, except that the standard says so? And is there any switch I can make gcc accept this code, since it seems there is no technical issue, and I do not see why such code should not work from a pure language standpoint.

templates are not macros. Name lookup of symbols is done in two contexts: first, where you wrote the template, and second pass of only argument-dependent lookup (ADL, or Koeing Lookup) when you pass the template a type (when the template "factory" is instantiated into an actual class or function).
When the function is in the same namespace as A, it is found via ADL. When it is not, it will not be. So when you moved the bar function into space::bar, it was no longer ADL-found with an argument of type A.
This is intentional, to both prevent your template from meaning completely different things at different spots, and to allow non-member interface extensions to types in their own namespace only.
Either use a traits class, stick such helper functions in the same namespace as the type, or pass in functors.
A traits class is probably easiest. Create a class with a static function foo (if you want a default implementation: otherwise leave empty). Call it from your template. Specialize it for A. Now you can implement special behavior for your A type at that point -- it could even call your space::bar function if that function is in view.
Putting bar in the same namespace as A is another solution, and I find it scales better than traits classes. Many of my personal traits classes end up falling back on an ADL lookup, as that lets me inject the handling code right next to where I define A. (The use of traits classes lets me also have my trait handle things in std, where I am not allowed to inject functions for ADL purposes for types living in std (you can inject ADL functions into std, but only for your own types))
The functor solution is how std::map works -- while it falls back on std::less<T> which falls back on operator<, it takes a functor that lets you specify how the key type should be compared within this map.

Is there any sane reason for this behaviour, except that the standard says so?
Sane or not, C++ usually requires names to be declared before use. You don't declare bar before using it; specifically, using namespace space only imports names that have been declared at that point, and not bar.
(If you care about the reason, it's because C++ inherited its declaration rules from the languages of half a century ago, when computers were somewhat primitive. Rules like this allowed compilation in a single pass, so that the compiler didn't have to keep waiting for the operator to put the stack of punch cards back into the hopper. Or something like that; I'm not quite sure how computers worked back then.)
And is there any switch I can make gcc accept this code
As the error message says, -fpermissive. But your code won't be portable if you don't stick to the standard.

This error has nothing to do with namespaces or templates at all, but is the standard error of using a function before it has been declared. Just as you cannot do:
void caller() { callee(); }
void callee() {}
But must instead do:
void callee() {}
void caller() { callee(); }
Or:
void callee();
void caller() { callee(); }
void callee() {}
... the same applies for more complicated functions involving templates and namespaces. Note that if you reorder slightly, it works just fine:
class A {
};
namespace space {
void bar(const A& a){
}
}
template <typename T> struct C
{
void foo() {
using namespace space;
bar(t);
}
T t;
};
int main()
{
C<A> c;
c.foo();
return 0;
}

Related

Warning about shadowed type definitions

Situation as follows:
in a codebase a header which defines some types, mostly convinient shortcuts like u64 for uint64_t exists. These definitions are global, as general type definitions do not really make sense when encapsulated in a namespace. This header is used in almost any other file to unify the codebase.
Also a public availible header only library is used, which happens to define the same name. In fact the other definition is not a type but a parameter name like:
void function(uint64_t u64);
Now the compiler throws warnings about that the parameter name shadows the global type definition. Which is correct in some respect.
But as the common global type-management header is needed and the include for the library is also needed, my question is how to resolve that problem in a sane way.
Also, why a type name can be shadowed by a function parameter/argument name, as a variable name and a typename are two very different things. That sounds more like a bug in the compiler to me. Without having sound knowlege about the standard in that topic, I would assume
using mytype = unsigned int;
void myfunc(mytype mytype);
to be valid, as I just have defined a variable to have the same name as a type, but the compiler can always distinguish both, because of the syntax.
Additional Question:
why the include order of both headers seems to have no effect.
I tried to solve the problem by including the external library header first (so the global type shortcut should not exist in that module) and included the common global header which defines the types later. But the Warnings persist.
Edited to preceise the problem (2 times)
But as the common global type-management header is needed and the include for the library is also needed, my question is how to resolve that problem in a sane way.
One thing you could do is to isolate the code that utilized the headers that produce that error and move it into its own compilation unit for which you silent that shadowing error message.
Also, why a type name can be shadowed by a function parameter/argument name, as a variable name and a typename are two very different things.
They are two different things, but there are cases where the syntax for both would be the same, so the compiler has to decide whether to use the parameter or the type.
Here one example, with static_assert, might be odd, but maybe there are other situations where this can be actually hard to debug:
#include <utility>
struct Type {
constexpr bool operator == (int i) {
return i==102;
}
};
template <typename X>
constexpr void f1(X Type) {
// does not fail because lambda is called which returns 101
static_assert(Type() == 101, "");
}
void f2() {
// fails because the operator == checks against 102
static_assert(Type() == 101, "");
}
int main() {
f1([] { return 101; });
f2();
return 0;
}
Here is probably a better example, maybe still an odd one but I could imagine that this one is more likely to occur:
bar(TypeA()); would not construct TypeA directly but TypeA operator () is called on the object of type TypeB:
#include <utility>
struct TypeA {
void operator () () {
}
};
struct TypeB {
TypeA operator () () {
return TypeA();
}
};
void bar(TypeA a) {
}
void foo(TypeB TypeA ) {
bar(TypeA());
}
int main() {
foo(TypeB());
}

Why this code works (C++ template class with invalid non-template function)? [duplicate]

This question already has an answer here:
Why are some functions within my template class not getting compiled?
(1 answer)
Closed 2 years ago.
This C++ code builds successfully:
void h(int *)
{
}
template <typename T>
class A
{
public:
void f()
{
T *val;
h(val);
}
};
int main()
{
A<const int> a;
}
Why?
It is undeniable that A<const int>::f() cannot work.
If you call a.f(), it fails to build as expected.
Why is an instance of A<const int> even allowed to exist then?
I'm not sure how SFINAE applies here.
I'd appreciate a C++ standard quote or a relevant link.
It's allowed to exist because it can still be useful for it to exist.
Consider std::vector, which has a one-argument overload of resize, which default-constructs new elements. Definitely useful! But it's also useful to have a std::vector of some type which isn't default-constructible, when you don't intend to resize it in that way. Forcing all member functions to be available, even those not needed by the user, would artificially restrict the applicability of a class.
There's no sfinae here. If we look closely at the declaration of the function, and not it's implementation:
template <typename T>
class A
{
public:
void f();
};
You can see that there's nothing to tell the compiler that this function should not be part of overload resolution.
If we add a return type containing an expression, this is different:
template <typename T>
class A
{
public:
auto f() -> decltype(void(h(std::declval<T*>())));
};
That's different. Now The compiler need to resolve h(T*) to perform overload resolution. If the substitution fails (the instantiation of the function declaration) then the function is not part of the set.
As for why the code still compiles, take a look at this:
void h(int *)
{
}
template <typename T>
class A
{};
template<typename T>
void f()
{
T *val;
h(val);
}
int main()
{
A<const int> a;
}
It's undeniable that f(A<const int>) cannot work
If you call f(a), it fails to build as expected.
Why is an instance of A<const int> even allowed to exist then?
The answer should become obvious now: the function is never instantiated!
The very same applies for member functions. There is no use to instantiate all member function if you don't use them.
If you look for an official statement that comfirm this behavior, then look no further than the standard itself.
From [temp.inst]/4 (emphasis mine):
Unless a member of a class template or a member template is a declared specialization, the specialization of the member is implicitly instantiated when the specialization is referenced in a context that requires the member definition to exist or if the existence of the definition of the member affects the semantics of the program; in particular, the initialization (and any associated side effects) of a static data member does not occur unless the static data member is itself used in a way that requires the definition of the static data member to exist.

Visibility of members of base template class not directly inherited

The access to members of a template base class requires the syntax this->member or the using directive. Does this syntax extends also to base template classes which are not directly inherited?
Consider the following code:
template <bool X>
struct A {
int x;
};
template <bool X>
struct B : public A<X> {
using A<X>::x; // OK even if this is commented out
};
template <bool X>
struct C : public B<X> {
// using B<X>::x; // OK
using A<X>::x; // Why OK?
C() { x = 1; }
};
int main()
{
C<true> a;
return 0;
}
Since the declaration of the template class B contains using A<X>::x, naturally the derived template class C can access to x with a using B<X>::x. Nevertheless, on g++ 8.2.1 and clang++ 6.0.1 the above code compiles fine, where x is accessed in C with a using that picks up x directly from A
I would have expected that C can not access directly to A. Also, commenting out the using A<X>::x in B still makes the code to compile. Even the combination of commenting out using A<X>::x in B and at the same time employ in C using B<X>::x instead of using A<X>::x gives a code that compiles.
Is the code legal?
Addition
To be more clear: the question arises on template classes and it is about the visibility of members inherited by template classes.
By standard public inheritance, the public members of A are accessible to C, so using the syntax this->x in C one does indeed get access to A<X>::x. But what about the using directive? How does the compiler correctly resolve the using A<X>::x if A<X> is not a direct base of C?
You are using A<X> where a base class is expected.
[namespace.udecl]
3 In a using-declaration used as a member-declaration, each
using-declarator's nested-name-specifier shall name a base class of
the class being defined.
Since this appears where a class type is expected, it is known and assumed to be a type. And it is a type that is dependent on the template arguments, so it's not looked up immediately.
[temp.res]
9 When looking for the declaration of a name used in a template
definition, the usual lookup rules ([basic.lookup.unqual],
[basic.lookup.argdep]) are used for non-dependent names. The lookup of
names dependent on the template parameters is postponed until the
actual template argument is known ([temp.dep]).
So it's allowed on account of the compiler not being able to know any better. It will check the using declaration when the class is instantiated. Indeed, one can put any dependent type there:
template<bool> struct D{};
template <bool X>
struct C : public B<X> {
using D<X>::x;
C() { x = 1; }
};
This will not be checked until the value of X is known. Because B<X> can bring with it all sorts of surprises if it's specialized. One could for instance do this:
template<>
struct D<true> { char x; };
template<>
struct B<true> : D<true> {};
Making the above declaration be correct.
Is the code legal?
Yes. This is what public inheritance does.
Is it possible to allow a template class derived from B to access to x only via this->x, using B::x or B::x? ...
You can use private inheritance (i.e. struct B : private A<X>), and arrange access to A<X>::x only through B's public/protected interface.
Also, if you're worried about having hidden members, you should use class instead of struct and specify the desired visibility explicitly.
Regarding the addition, note that:
(1) the compiler knows what object A<X>::x refers to given some instance of A<X> (because A is defined in the global scope, and X is the template parameter of C).
(2) You do indeed have an instance of A<X> - this is a ponter to a derived class (it doesn't matter if A<X> is a direct base class or not).
(3) The object A<X>::x is visible in the current scope (because the inheritances and the object itself are public).
The using statement is merely syntactic sugar. Once all types are resolved, the compiler replaces following use of x with the appropriate memory address in the instance, not unlike writing this->x directly.
Maybe this example could give you some idea as to why should it be legal:
template <bool X>
struct A {
int x;
};
template <bool X>
struct B : public A<X> {
int x;
};
template <bool X>
struct C : public B<X> {
//it won't work without this
using A<X>::x;
//or
//using B<X>::x;
C() { x = 1; }
// or
//C() { this -> template x = 1; }
//C() { this -> x = 1; }
};
In case of choosing C() { this -> template x = 1; } the last inherited x (B::x) would be assigned to 1 not the A::x.
It can simply be tested by:
C<false> a;
std::cout << a.x <<std::endl;
std::cout << a.A::x <<std::endl;
std::cout << a.B::x <<std::endl;
Assuming that the programmer for struct B was not aware of struct A members, but the programmer of struct c was aware of members of both, it seems very reasonable for this feature to be allowed!
As to why should compiler be able to recognize using A<X>::x; when it is used in C<X> , consider the fact that within the definition of a class/class template all the direct/indirect inherited bases are visible regardless of the type of inheritance. But only the publicly inherited ones are accessible!
For example if it was like:
using A<true>::x;
//or
//using B<true>::x;
Then there would be a problem by doing:
C<false> a;
Or wise versa. since neither A<true> or B<true> is a base for C<false>, therefor visible. But since it is like:
using A<X>::x;
Because the generic term X is used in order to define the term A<X>, it is first deducible second recognizable, since any C<X> (if is not specialized later) is indirectly based on A<X> !
Good Luck!
template <bool X>
struct C : public B<X> {
// using B<X>::x; // OK
using A<X>::x; // Why OK?
C() { x = 1; }
};
The question is why wouldn't that be supported? Because the constrain that A<X> is a base of a specialization of the main template definition of C is a question that can only be answered, and that only makes sense for a particular template argument X?
To be able to check templates at definition time was never a design goal of C++. Many well formed-ness constrains are checked at instanciation time and this is fine.
[Without a true concept (necessary and sufficient template parameter contracts) support no variant of C++ would do significantly better, and C++ is probably too complicated and irregular to have true concepts and true separate checking of templates, ever.]
The principles that makes it necessary to qualify a name to make it dependent does not have anything with early diagnostic of errors in template code; the way name lookup works in template was considered necessary by the designers to support "sane" (actually slightly less insane) name lookup in template code: a use of a non local name in a template shouldn't bind too often to a name declared by the client code, as it would break encapsulation and locality.
Note that for any unqualified dependent name you can end up accidentally calling an unrelated clashing user function if it's a better match for overloading resolution, which is another problem that would be fixed by true concept contracts.
Consider this "system" (i.e. not part of current project) header:
// useful_lib.hh _________________
#include <basic_tool.hh>
namespace useful_lib {
template <typename T>
void foo(T x) { ... }
template <typename T>
void bar(T x) {
...foo(x)... // intends to call useful_lib::foo(T)
// or basic_tool::foo(T) for specific T
}
} // useful_lib
And that project code:
// user_type.hh _________________
struct UserType {};
// use_bar1.cc _________________
#include <useful_lib.hh>
#include "user_type.hh"
void foo(UserType); // unrelated with basic_tool::foo
void use_bar1() {
bar(UserType());
}
// use_bar2.cc _________________
#include <useful_lib.hh>
#include "user_type.hh"
void use_bar2() {
bar(UserType()); // ends up calling basic_tool::foo(UserType)
}
void foo(UserType) {}
I think that code is pretty realistic and reasonable; see if you can see the very serious and non local issue (an issue that can only be found by reading two or more distinct functions).
The issue is caused by the use of an unqualified dependent name in a library template code with a name that isn't documented (intuitivement shouldn't have to be) or that is documented but that the user wasn't interested in, as he never needed to override that part of the library behavior.
void use_bar1() {
bar(UserType()); // ends up calling ::foo(UserType)
}
That wasn't intended and the user function might have a completely different behavior and fails at runtime. Of course it could also have an incompatible return type and fail for that reason (if the library function returned a value unlike in that example, obviously). Or it could create an ambiguity during overload resolution (more involved case possible if the function takes multiple arguments and both library and user functions are templates).
If this wasn't bad enough, now consider linking use_bar1.cc and use_bar2.cc; now we have two uses of the same template function in different contexts, leading to different expansions (in macro-speak, as templates are only slightly better than glorified macros); unlike preprocessor macros, you are not allowed to do that as the same concrete function bar(UserType) is being defined in two different ways by two translation units: this is an ODR violation, the program is ill formed no diagnostic required. That means that if the implementation doesn't catch the error at link time (and very few do), the behavior at runtime is undefined from start: no run of the program has defined behavior.
If you are interested, the design of name lookup in template, in the era of the "ARM" (Annotated C++ Reference Manual), long before ISO standardization, is discussed in D&E (Design and Evolution of C++).
Such unintentional binding of a name was avoided at least with qualified names and non dependent names. You can't reproduce that issue with a non dependent unqualified names:
namespace useful_lib {
template <typename T>
void foo(T x) { ... }
template <typename T>
void bar(T x) {
...foo(1)... // intends to call useful_lib::foo<int>(int)
}
} // useful_lib
Here the name binding is done such that no better overload match (that is no match by a non template function) can "beat" the specialization useful_lib::foo<int> because the name is bound in the context of the template function definition, and also because useful_lib::foo hides any outside name.
Note that without the useful_lib namespace, another foo that happened to be declared in another header included before could still be found:
// some_lib.hh _________________
template <typename T>
void foo(T x) { }
template <typename T>
void bar(T x) {
...foo(1)... // intends to call ::foo<int>(int)
}
// some_other_lib.hh _________________
void foo(int);
// user1.cc _________________
#include <some_lib.hh>
#include <some_other_lib.hh>
void user1() {
bar(1L);
}
// user2.cc _________________
#include <some_other_lib.hh>
#include <some_lib.hh>
void user2() {
bar(2L);
}
You can see that the only declarative difference between the TUs is the order of inclusion of headers:
user1 causes the instanciation of bar<long> defined without foo(int) visible and name lookup of foo only finds the template <typename T> foo(T) signature so binding is obviously done to that function template;
user2 causes the instanciation of bar<long> defined with foo(int) visible so name lookup finds both foo and the non template one is a better match; the intuitive rule of overloading is that anything (function template or regular function) that can match less argument lists wins: foo(int) can only match exactly an int while template <typename T> foo(T) can match anything (that can be copied).
So again the linking of both TUs causes an ODR violation; the most likely practical behavior is that which function is included in the executable is unpredictable, but an optimizing compiler might assume that the call in user1() does not call foo(int) and generate a non inline call to bar<long> that happens to be the second instanciation that ends up calling foo(int), which might cause incorrect code to be generated [assume foo(int) could only recurse through user1() and the compiler sees it doesn't recurse and compile it such that recursion is broken (this can be the case if there is a modified static variable in that function and the compiler moves modifications across function calls to fold successive modifications)].
This shows that templates are horribly weak and brittle and should be used with extreme care.
But in your case, there is no such name binding issue, as in that context a using declaration can only name a (direct or indirect) base class. It doesn't matter that the compiler cannot know at definition time whether it's a direct or indirect base or an error; it will check that in due time.
While early diagnostic of inherently erroneous code is permitted (because sizeof(T()) is exactly the same as sizeof(T), the declared type of s is illegal in any instantiation):
template <typename T>
void foo() { // template definition is ill formed
int s[sizeof(T) - sizeof(T())]; // ill formed
}
diagnosing that at template definition time is not practically important and not required for conforming compilers (and I don't believe compiler writers try to do it).
Diagnostic only at the point of instantiation of issues that are guaranteed to be caught at that point is fine; it does not break any design goal of C++.

MISRA C++ Rule 14-5-1: Name of generic function template declared in namespace associated with type

Is Warning 1573 ("Name of generic function template declared in namespace associated with type") really relevant when the namespace is an
anonymous namespace? Most of the helper functions I have for tests go in unnamed namespace and it breaks the above rule.
Example:
namespace
{
template <typename T>
T template_func(T arg)
{
return arg;
}
class foo {};
}
int main()
{
return template_func(0);
}
How do I get around in the above, to satisfy the rule?
As state in their example, you might use extra namespace, something like:
namespace
{
template< class T >
T template_func(T arg) { return arg; }
namespace X
{
class foo{};
}
using X::foo;
}
int main()
{
return template_func(0);
}
I'd guess that it isn't aimed at polluting global namespace but to avoid class picking up weird matches from generic templates belonging to the same namespace.
It goes along the cpp core guideline T.47: Avoid highly visible unconstrained templates with common names
Specifically:
Reason :
An unconstrained template argument is a perfect match for anything so such a template can be preferred over more specific types that require minor conversions. This is particularly annoying/dangerous when ADL is used. Common names make this problem more likely.
Note:
If an unconstrained template is defined in the same namespace as a type, that unconstrained template can be found by ADL (as happened in the example). That is, it is highly visible.
As for how to bypass it, Jarod42 was 1st with an example in his answer.

place utility routines be in the same namespace as the types it uses?

I've got a bunch of my own objects which I've dutifully put inside my own namespace:
namespace my { struct foo final {}; /* etc. */}
Where should I put non-member non-friend functions (i.e., "global" utility routines) which take my types as parameters? Should I also put them in the my namespace
namespace my { extern void f(const foo&); }
Or, is there an upside (or downside) to put them in the global namespace
extern void f(const my::foo&);
In either case, the argument to f is my::foo, so does it matter whether the function itself is actually named ::f() or my::f()?
Edit: note that I'm specifically not looking for "I like global" or "I like in the namespace" (or similar). Rather, I'm seeking specific technical reasons to prefer one approach over the other (assuming such differences actually exist). From a comment, it sounds like one (the?) factor to consider may be ADL behavior; are there others?
Putting operations tightly coupled to a type in the same namespace as the type permits Argument Dependent Lookup or Koenig lookup to work.
Polluting the global namespace is often a bad idea; you only get one global namespace, and if your code doesn't play with what someone else put there, there are few solutions.
For example, if you have a type or function named CString in the global namespace and you try to include and use MFC code which injects a CString into the global namespace, you are screwed.
Placing code in a namespace means you pollute the global namespace with one token, instead of one per function and type name (etc).
A second thing to consider is if your types are template generated, placing a friend function within the template results in an ADL-discoverable non-template function which is found when interacting with instances of the class instances of the template.
namespace my {
template<class T>
struct foo {
friend foo operator+( foo lhs, foo rhs ) { return {lhs.x+rhs.x}; }
friend foo add( foo lhs, foo rhs ) { return {lhs.x+rhs.x}; }
int x;
};
}
now my::foo f0{0},f1{1}; auto f2 = add(f0, f1); works, as does auto f3=f0+f1;.
Both add and operator+ here are not templates, which means if we have a type that converts-to-foo, add(f0, converts_to_foo) also works.
It depends. Sometimes you have a function that takes two arguments from unrelated namespaces (e.g. in I/O or serialization), it could reside in either of those (but not in the global namespace!)
// foo can be either in N1 or N2, but not in global
namespace N1 { auto foo(A&, N2::B const&) }
namespace N2 { auto foo(N1::A&, B const&) }
Or you have an algorithm that is supposed to work for generic arguments (e.g. input and output ranges) you would put that function in its own namespace
// algo should probably be in its own namespace N
namespace N {
template<class R1, class R2>
auto algo(R1 const& in, R2& out)
}
Calling such an algorithm is best done without relying on ADL, i.e. as N::algo(rin, rout).