You may have notice that later versions of gcc is more strict with standards (see this question)
All inherited members of a template class should be called using the full name, ie.
ParentClass<T>::member instead of just member
But still I have a lot of old code that does not respect this. Adding using ParentClass<T>::member for each used member in each class is quite a pain. Is there is a way to do something like using ParentClass<T>::* ?. I would like this better than deactivating this check in g++ but if there is now way, how can I deactivate it ?
Edit:
According to C++ FAQ (thanks sth) these are the only way to correctly solve the inherited member variable names :
Change the call from f() to this->f(). Since this is always implicitly dependent in a template, this->f is dependent and the lookup is therefore deferred until the template is actually instantiated, at which point all base classes are considered.
Insert using B<T>::f; just prior to calling f().
Change the call from f() to B<T>::f().
So now looking for the right switch to deactivate the full name resolution ...
Not really an answer to you question, but you can also write this->member instead of ParentClass<T>::member. This is most often easier to write and makes the compiler look for member in the right places.
Related
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
name hiding and fragile base problem
I'm familiar with the rules involving member function hiding. Basically, a derived class with a function that has the same name as a base class function doesn't actually overload the base class function - it completely hides it.
struct Base
{
void foo(int x) const
{
}
};
struct Derived : public Base
{
void foo(const std::string& s) { }
};
int main()
{
Derived d;
d.foo("abc");
d.foo(123); // Will not compile! Base::foo is hidden!
}
So, you can get around this with a using declaration. But my question is, what is the reason for base class function hiding? Is this a "feature" or just a "mistake" by the standards committee? Is there some technical reason why the compiler can't look in the Base class for matching overloads when it doesn't find a match for d.foo(123)?
Name lookup works by looking in the current scope for matching names, if nothing is found then it looks in the enclosing scope, if nothing is found it looks in the enclosing scope, etc. until reaching the global namespace.
This isn't specific to classes, you get exactly the same name hiding here:
#include <iostream>
namespace outer
{
void foo(char c) { std::cout << "outer\n"; }
namespace inner
{
void foo(int i) { std::cout << "inner\n"; }
void bar() { foo('c'); }
}
}
int main()
{
outer::inner::bar();
}
Although outer::foo(char) is a better match for the call foo('c') name lookup stops after finding outer::inner::foo(int) (i.e. outer::foo(char) is hidden) and so the program prints inner.
If member function name weren't hidden that would mean name lookup in class scope behaved differently to non-class scope, which would be inconsistent and confusing, and make C++ even harder to learn.
So there's no technical reason the name lookup rules couldn't be changed, but they'd have to be changed for member functions and other types of name lookup, it would make compilers slower because they'd have to continue searching for names even after finding matching names in the current scope. Sensibly, if there's a name in the current scope it's probably the one you wanted. A call in a scope A probably wants to find names in that scope, e.g. if two functions are in the same namespace they're probably related (part of the same module or library) and so if one uses the name of the other it probably means to call the one in the same scope. If that's not what you want then use explicit qualification or a using declaration to tell the compiler the other name should be visible in that scope.
Is this a "feature" or just a "mistake" by the standards committee?
It's definitely not a mistake, since it's clearly stipulated in the standard. It's a feature.
Is there some technical reason why the compiler can't look in the Base class for matching overloads when it doesn't find a match for d.foo(123)?
Technically, a compiler could look in the base class. Technically. But if it did, it would break the rules set by the standard.
But my question is, what is the reason for base class function hiding?
Unless someone from the committee comes with an answer, I think we can only speculate. Basically, there were two options:
if I declare a function with the same name in a derived class, keep the base class's functions with the same name directly accessible through a derived class
don't
It could have been determined by flipping a coin (...ok, maybe not).
In general, what are the reasons for wanting a function with the same name as that of a base class? There's different functionality - where you'd more likely use polymorphism instead. For handling different cases (different parameters), and if these cases aren't present in the base class, a strategy pattern might be more appropriate to handle the job. So most likely function hiding comes in effect when you actually do want to hide the function. You're not happy with the base class implementation so you provide your own, with the option of using using, but only when you want to.
I think it's just a mechanism to make you think twice before having a function with the same name & different signature.
I believe #Lol4t0 is pretty much correct, but I'd state things much more strongly. If you allowed this, you'd end up with two possibilities: either make a lot of other changes throughout almost the entirety of the language, or else you end up with something almost completely broken.
The other changes you'd make to allow this to work would be to completely revamp how overloading is done -- you'd have to change at least the order of the steps that were taken, and probably the details of the steps themselves. Right now, the compiler looks up the name, then forms an overload set, resolves the overload, then checks access to the chosen overload.
To make this work even sort of well, you'd pretty much have to change that to check access first, and only add accessible functions to the overload set. With that, at least the example in #Lol4t0's answer could continue to compile, because Base::foo would never be added to the overload set.
That still means, however, that adding to the interface of the base class could cause serious problems. If Base didn't originally contain foo, and a public foo were added, then the call in main to d.foo() would suddenly do something entirely different, and (again) it would be entirely outside the control of whoever wrote Derived.
To cure that, you'd just about have to make a fairly fundamental change in the rules: prohibit implicit conversions of function arguments. Along with that, you'd change overload resolution so in case of a tie, the most derived/most local version of a function was favored over a less derived/outer scope. With those rules, the call to d.foo(5.0) could never resolve to Derived::foo(int) in the first place.
That, however, would only leave two possibilities: either calls to free functions would have different rules than calls to member functions (implicit conversions allowed only for free functions) or else all compatibility with C would be discarded entirely (i.e., also prohibit implicit conversions in all function arguments, which would break huge amounts of existing code).
To summarize: to change this without breaking the language entirely, you'd have to make quite a few other changes as well. It would almost certainly be possible to create a language that worked that way, but by the time you were done it wouldn't be C++ with one minor change -- it would be an entirely different language that wasn't much like C++ or C, or much of anything else.
I can only propose, that this decision was made to make things simpler.
Imagine, that derived function will overload base one. Then, does the following code should generate compilation error, or use Deriveds function?
struct Base
{
private:
void foo(float);
}
struct Derived: public Base
{
public:
void foo(int);
}
int main()
{
Derived d;
d.foo(5.0f);
}
According to existing behavior of overloads this should generate error.
Now imagine, in the first version Base had no foo(float). In second version it appears. Now changing the realization of base class breaks interface of derived.
If you are developer of Derived and cannot influence developers of Base and a lot of clients use your interface, you are in a bad situation now.
Recently I attempted to detect existence of specific private constructors and ran into the issue that std::is_constructible only checks the immediate context and thus would not recognize anything such constructors. After some research I did see that one answer here mentioned that the proper way is to friend the class in question with std::is_constructible to allow it to have access.
To test if this method worked, I attempted the following test code
#include <type_traits>
class A {
private:
template<typename, typename ...>
friend struct std::is_constructible;
A() = default;
};
int main() {
static_assert(std::is_constructible<A>::value);
static_assert(std::is_constructible_v<A>);
}
Interestingly, this method did appear to work with std::is_constructible in Visual Studio 2017, though I then began to encounter issues with std::is_constructible_v. In their implementation, rather than using an alias template to the actual struct std::is_constructible itself, they instead call the intrinsic used internally directly which in turn ignores the friend declaration.
Thinking that this was a bug with their standard library implementation, I then tested in other compilers and found that neither clang nor gcc were able to pass this assertion in any case, causing me to wonder if it is even supposed to work like this at all (some of the comments on the linked post seem to suggest it's a bug while others say it should not take friend declarations into account).
Thus, the main question is should this code work correctly (as in should it be able to access the private constructor and pass the assertions) with way the standard defines the access being limited to an immediate context? A similar question was also posed here, the main thing I am unsure about is the exact definition intended by an "immediate context" in this case since this is slightly different than the example in the linked question.
A relevant passage from N4713 23.15.4.3.8 [meta.unary.prop]/8:
Access checking is performed as if in a context unrelated to T and any
of the Args. Only the validity of the immediate context of the
variable initialization is considered.
After some research I did see that one answer here mentioned that the proper way is to friend the class in question with std::is_constructible to allow it to have access.
No. Definitely not. This is not the proper way at all. There is no guarantee whatsoever that this will work.
Moreover, there is no guarantee whatsoever that friending anything in the standard library will do what you want it to. The standard library is not your friend. P1339 was approved in Kona and will update SD-8 to give the standard library the right to assume that users do not do this... and the library will not care if changes break user friendship like this.
std::is_constructible_v<A> is, and should be, false.
The "immediate context of the variable initialization" is specifically talking about is_constructible_v, which is a variable template that is initialized to the value of is_constructible with the same arguments. That is, the initialization happens outside of your code, so the context within your code where it fetches the value of said variable is irrelevant to the accessibility of the constructors. The value fetched will be the same no matter from where it is accessed.
Coupled with the first sentence, the standard effectively says "this only looks for publicly accessible stuff".
Can someone give a hint how does compiler process expressions such as
class DerivedA: public ParentTemplateClass<DerivedA>{
}
For mee it looks like:
this boy's father is a "son" of this boy
I mean it's not obvious for me how "parsing" of the class DerivedA can be completed WITHOUT knowing the exactly "description" of parent class. Seems' it can not. So parent class must be processed before children, but in such situation parent depends on children..and I'm stuck there.
Yeah there some articles on the web which describe usage of such thing, e.g. an article about Curiously Recurring Template Pattern (
http://en.wikibooks.org/wiki/More_C++_Idioms/Curiously_Recurring_Template_Pattern) but that's not some kind of standart or smth near. There must be clear behaviour description such as operations ordering isn't it?
ANSWERED:
Thnx to everyone. Yeah forward decl analogy seems legit for me to stop damaging my brain. Templates are still state of art for me cause of its hidden sublanguage nature and i cant just g++ -E :)
After your code says class DerivedA, the symbol DerviedA is declared. At the point it can be used as a template parameter. C++ compilers do several passes on the code, so at that point in parsing the compiler will "believe" that your intention was correct and that it will eventually get the definition of that class (when it is about to instantiate the template, i.e. you actually use that type). If not, it will complain at that point. A similar thing happens if you used a forward declared class in a declaration but didn't provide a definition before using it.
At the point at which the template is instantiated, DerivedA is incomplete; it has been declared, but not fully defined. Incomplete types can be used in various ways - for example, you can declare pointers or references to them, declare functions with them as return or parameter types, and a few other things. You can't create objects, inherit from them, access their members, or in general do anything that requires more information than just the class name.
As long as the class template only does these things, there is no problem.
I think to understand how this could work, you need too understand more about C++ templates in general, than just the Curiously Recurring Template Pattern. Someone else can probably answer this better than me, but I know that C++ can't fully parse a template class definition by itself. It instantiates the template each time it is used in the code. If each class was in a separate include file, think of it like this:
#include "ParentTemplateClass.h" // C++ initially validates the template class definition's syntax.
#include "DerivedA.h" // First use of ParentTemplateClass -
// at this point it becomes fully instantiated.
The C++ parser will initially validate the template's syntax when it sees the template definition. Then, when the template is used as a base of DerivedA, the parsing continues and the template is fully instantiated. This is, of course, a simplified view of the parsing that the C++ compiler will do, and I'm sure the details vary by compiler. See also http://womble.decadent.org.uk/c++/template-faq.html#disambiguation.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
name hiding and fragile base problem
I'm familiar with the rules involving member function hiding. Basically, a derived class with a function that has the same name as a base class function doesn't actually overload the base class function - it completely hides it.
struct Base
{
void foo(int x) const
{
}
};
struct Derived : public Base
{
void foo(const std::string& s) { }
};
int main()
{
Derived d;
d.foo("abc");
d.foo(123); // Will not compile! Base::foo is hidden!
}
So, you can get around this with a using declaration. But my question is, what is the reason for base class function hiding? Is this a "feature" or just a "mistake" by the standards committee? Is there some technical reason why the compiler can't look in the Base class for matching overloads when it doesn't find a match for d.foo(123)?
Name lookup works by looking in the current scope for matching names, if nothing is found then it looks in the enclosing scope, if nothing is found it looks in the enclosing scope, etc. until reaching the global namespace.
This isn't specific to classes, you get exactly the same name hiding here:
#include <iostream>
namespace outer
{
void foo(char c) { std::cout << "outer\n"; }
namespace inner
{
void foo(int i) { std::cout << "inner\n"; }
void bar() { foo('c'); }
}
}
int main()
{
outer::inner::bar();
}
Although outer::foo(char) is a better match for the call foo('c') name lookup stops after finding outer::inner::foo(int) (i.e. outer::foo(char) is hidden) and so the program prints inner.
If member function name weren't hidden that would mean name lookup in class scope behaved differently to non-class scope, which would be inconsistent and confusing, and make C++ even harder to learn.
So there's no technical reason the name lookup rules couldn't be changed, but they'd have to be changed for member functions and other types of name lookup, it would make compilers slower because they'd have to continue searching for names even after finding matching names in the current scope. Sensibly, if there's a name in the current scope it's probably the one you wanted. A call in a scope A probably wants to find names in that scope, e.g. if two functions are in the same namespace they're probably related (part of the same module or library) and so if one uses the name of the other it probably means to call the one in the same scope. If that's not what you want then use explicit qualification or a using declaration to tell the compiler the other name should be visible in that scope.
Is this a "feature" or just a "mistake" by the standards committee?
It's definitely not a mistake, since it's clearly stipulated in the standard. It's a feature.
Is there some technical reason why the compiler can't look in the Base class for matching overloads when it doesn't find a match for d.foo(123)?
Technically, a compiler could look in the base class. Technically. But if it did, it would break the rules set by the standard.
But my question is, what is the reason for base class function hiding?
Unless someone from the committee comes with an answer, I think we can only speculate. Basically, there were two options:
if I declare a function with the same name in a derived class, keep the base class's functions with the same name directly accessible through a derived class
don't
It could have been determined by flipping a coin (...ok, maybe not).
In general, what are the reasons for wanting a function with the same name as that of a base class? There's different functionality - where you'd more likely use polymorphism instead. For handling different cases (different parameters), and if these cases aren't present in the base class, a strategy pattern might be more appropriate to handle the job. So most likely function hiding comes in effect when you actually do want to hide the function. You're not happy with the base class implementation so you provide your own, with the option of using using, but only when you want to.
I think it's just a mechanism to make you think twice before having a function with the same name & different signature.
I believe #Lol4t0 is pretty much correct, but I'd state things much more strongly. If you allowed this, you'd end up with two possibilities: either make a lot of other changes throughout almost the entirety of the language, or else you end up with something almost completely broken.
The other changes you'd make to allow this to work would be to completely revamp how overloading is done -- you'd have to change at least the order of the steps that were taken, and probably the details of the steps themselves. Right now, the compiler looks up the name, then forms an overload set, resolves the overload, then checks access to the chosen overload.
To make this work even sort of well, you'd pretty much have to change that to check access first, and only add accessible functions to the overload set. With that, at least the example in #Lol4t0's answer could continue to compile, because Base::foo would never be added to the overload set.
That still means, however, that adding to the interface of the base class could cause serious problems. If Base didn't originally contain foo, and a public foo were added, then the call in main to d.foo() would suddenly do something entirely different, and (again) it would be entirely outside the control of whoever wrote Derived.
To cure that, you'd just about have to make a fairly fundamental change in the rules: prohibit implicit conversions of function arguments. Along with that, you'd change overload resolution so in case of a tie, the most derived/most local version of a function was favored over a less derived/outer scope. With those rules, the call to d.foo(5.0) could never resolve to Derived::foo(int) in the first place.
That, however, would only leave two possibilities: either calls to free functions would have different rules than calls to member functions (implicit conversions allowed only for free functions) or else all compatibility with C would be discarded entirely (i.e., also prohibit implicit conversions in all function arguments, which would break huge amounts of existing code).
To summarize: to change this without breaking the language entirely, you'd have to make quite a few other changes as well. It would almost certainly be possible to create a language that worked that way, but by the time you were done it wouldn't be C++ with one minor change -- it would be an entirely different language that wasn't much like C++ or C, or much of anything else.
I can only propose, that this decision was made to make things simpler.
Imagine, that derived function will overload base one. Then, does the following code should generate compilation error, or use Deriveds function?
struct Base
{
private:
void foo(float);
}
struct Derived: public Base
{
public:
void foo(int);
}
int main()
{
Derived d;
d.foo(5.0f);
}
According to existing behavior of overloads this should generate error.
Now imagine, in the first version Base had no foo(float). In second version it appears. Now changing the realization of base class breaks interface of derived.
If you are developer of Derived and cannot influence developers of Base and a lot of clients use your interface, you are in a bad situation now.
Here is some CRTP based template code that I used to try and resolve this question: Requiring overridden virtual functions to call base implementations. I would post code here, but the lines are long and easier to read on codepad.org (if needed I'll post here). It's ugly and it's somewhat artificial, of course, although it does work. But what I didn't realize at first, that while it compiles on both MSVC++ and GCC, some template types are not really defined. The part I'm questioning is several long inner if( typeid( Derived(N) ) != typeid( Derived(N-1)) (symbolic notation) in TBase::OnEvent function on top.
You cannot typdef these types, it will be a compilation error - there is simply not enough derived classes for type to be defined with such long ...::TDerived::... chain, so you'll get, correctly, compilation error TDerived is not defined in TBase. Yet compiler eats them through typeid. When I checked in debugger MSVC++ compiler output (with full symbolic info), it seems that all those long ...::TDerived::... that should not really result in any class, in typeid resolved by compiler to simply the last TDerived04 in class chain. And RTTI is pulled for this last class in the class chain, independently of how many ...::TDerived::... I have.
Taking into account that both MSVC++ and GCC do that (although I only have access to GCC through codepad.org), my question is next: is it somehow defined behavior of typeid? Why then typedef of any of those long ...::TDerived::... does not resolve to TDerived04?
EDIT: I mean, I'm happy typedef does not resolve to TDerived04, that'd be disaster for anyone who uses typedef, but why such inconsistency between typeid and typedef?
EDIT: GCC accepts TDerived04::TDerived04::TDerived04::TDerived04 lD4; variable declaration. And the type is simply TDerived04 in the end. Is there a rule for collapsing scope resolution? Apparently, both MSVC++ and GCC seems to be doing the same in typeid, but MSVC++, unlike GCC, can't handle other scenarios - it gives compile error, requiring arguments for constructor(s).
I wouldn't consider using typeid as anything else than a tool for debugging. C++ standard only guarantees its existance, but doesn't really say what it should do. This renders this utitlity as nothing more than a way to print a human readable class names (please correct me if you know any other practical use).
I would say there is too much "compiler defined" behaviour of typeid to make it useful for anything else than above.
Approach presented in the solution also has a huge drawback. Besides being ugly and hard to maintain, the base class requires to know about all derived classes. This is quite a big design flaw.
As for alternative solution it can be seen here (code also posted in original question).
As for TDerived04::TDerived04::TDerived04::TDerived04 being valid is can be exaplained by that in TDerived04 class you can refer to this class/namespace using its name TDerived04. So TDerived04::TDerived04 is like pointing at class TDerived04 from TDerived04 (as #MSalters said it is called "class name injection").
The problem roughly is that there is an ambiguity between the injected class name and the constructor name. In the scope of class X, X can name the class itself, but X::X can also refer to the constructor - where that makes sense.