Does inheriting constructors work with templates in C++0x? - c++

In C++0x, you can use the using keyword to inherit constructors, like so:
class B { B(int) {} };
class A : public B { using B::B; };
Which will implicitly declare an A(int) constructor. Does this work with templates?
class B { B(int) {} };
template<class T> class A : public T { using T::T; };
Within T::T, I expect the compiler to figure out the left hand T since using the scope operator on template arguments is normal, but figuring out that the right hand T is the constructor is a special case. In fact it appears there's an ambiguity: what if I have a method called T in B that I'm trying to add overloads to in A (that's how a compiler would interpret such a using declaration pre-C++0x)?

Yes it works, and the reason is the name lookup mechanism. The mechanism a inheriting-constructors declaration works is simple: If the using declaration's name refers to base class constructors, that's an inheriting constructors declaration. At 3.4.3.1[class.qual]p2 we find:
In a lookup in which the constructor is an acceptable lookup result and the nested-name-specifier nominates a class C
if the name specified after the nested-name-specifier, when looked up in C, is the injected-class-name of C (Clause 9), or
in a using-declaration (7.3.3) that is a member-declaration, if the name specified after the nested-name-specifier is the same as the identifier or the simple-template-id's template-name in the last component of the nested-name-specifier
the name is instead considered to name the constructor of class C.
This is the paragraph that makes out of class constructor definitions work, and this is also the paragraph that makes inheriting constructor declarations work. The second bullet applies in this case:
struct B {
B(int) { }
};
typedef B mytype;
struct A : B {
// "name ... is the same as the identifier ... in the last component ..."
using mytype::mytype;
};
template<typename T> using same = T;
struct C : B {
// "name ... is the same as the template-name ... in the last component ..."
same<B>::same;
};
The latter example proves also useful in cases such as the following
template<template<typename> class Base>
struct X : Base<int> {
using Base<int>::Base;
};
In summary:
The first bullet above is a semantic rule - if the name after the nested name specifier refers to the injected class name (B::B or mytype::B), then it will be translated to refer to the constructor(s).
The second bullet is a syntactic rule - the names just must match - their meaning is irrelevant otherwise - there could have been a member called Base in the template argument provided to X, such as in the following, but the using declaration would still import the constructors and do not name the member Base:
template<typename T> struct D { private: T Base; };
X<D> x; // valid, the private member is *not* touched!

Yes, it appears it does, from the standard (Feb 2011 Draft), section 12.9:
template< class T >
struct D : T {
using T::T; // declares all constructors from class T
~D() { std::clog << "Destroying wrapper" << std::endl; }
};
Class template D wraps any class and forwards all of its constructors,
while writing a message to the standard log whenever an object of
class D is destroyed. —end example
Another thing to note, while the standard allows it, according to this list, only 1 compiler, IBM XLC++, supports this feature in a release version. GCC only currently supports it with a patch.
Edit: AJG85 pointed out that the T in the template always refers to the placeholder, so the 'using T::T' always refers to the template argument.

Related

Why can't "is_base_of" be used inside a class declaration (incomplete type)?

I completely see why this cannot work:
class Base {};
class A;
static_assert(std::is_base_of<Base, A>::value, "");
Because there is no information about a 'class hierarchy', but...
Why cannot the following work?
class Base {};
class A : public Base {
static_assert(std::is_base_of<Base, A>::value, "");
};
(produce: an undefined class is not allowed as an argument to compiler intrinsic type trait)
The type 'A' is still not complete at line with static_assert (according to definition of this concept). However - the compiler already knows the 'class hierarchy' and could provide the answer for this.
Of course - this static_assert could be moved to destructor or whatever to fix this issue, but there are situations where it cannot be done, for example:
class Base {};
template<typename T>
struct type_of {
static_assert(std::is_base_of<Base, T>::value, "T is not derived from Base");
using type = int; //* Some normal type in real use
};
class A : public Base {
public:
type_of<A>::type foo(); // Will not compile
};
Should it not be allowed?
A class definition is complete (that is, a class is considered defined) after the closing brace }.
In your case, when you try to use A with std::is_base_of, A isn't fully defined yet:
class A : public Base {
// no closing brace for A yet, thus A isn't fully defined here
static_assert(std::is_base_of<Base, A>::value, "");
};
On the other side, std::is_base_of requires types that are completely defined to work.
Thus the error.
As a workaround, you can put the assert in the destructor of A:
class A : public Base {
~A() {
static_assert(std::is_base_of<Base, A>::value, "");
}
};
In fact, a class type is considered fully defined in its member functions' bodies.
See here for more details (emphasis mine):
A class is considered a completely-defined object type ([basic.types]) (or complete type) at the closing } of the class-specifier. Within the class member-specification, the class is regarded as complete within function bodies, default arguments, noexcept-specifiers, and default member initializers (including such things in nested classes). Otherwise it is regarded as incomplete within its own class member-specification.
The doc page for std::is_base_of yields:
If both Base and Derived are non-union class types, and they are not
the same type (ignoring cv-qualification), Derived shall be a complete
type; otherwise the behavior is undefined.
The definition for a class is complete after you close its scope with }. Thus, in your case, an error is generated.
Note, that static assertion can appear in block or namespace / file scope. So you can move it outside the class' body or, if you don't want to have it in your header, move to the implementation file.

Why doesn't a using-declaration work to solve the diamond problem?

Please consider the following code:
struct A
{
void f()
{
}
};
struct B1 : A
{
};
struct B2 : A
{
};
struct C : B1, B2
{
void f() // works
{
B1::f();
}
//using B1::f; // does not work
//using B1::A::f; // does not work as well
};
int main()
{
C c;
c.f();
return 0;
}
I kindly ask you not to copy paste a standard reply on how to solve the diamond problem ("use virtual inheritance"). What I am asking here is why doesn't a using-declaration work in this case. The exact compiler error is:
In function 'int main()':
prog.cpp:31:6: error: 'A' is an ambiguous base of 'C'
c.f();
I got the impression a using-declaration should work from this example:
struct A
{
void f()
{
}
};
struct B
{
void f()
{
}
};
struct C : A, B
{
using A::f;
};
int main()
{
C c;
c.f(); // will call A::f
return 0;
}
Someone else can find the standard quote but I'm going to explain conceptually.
It doesn't work because a using-declaration only affects name lookup.
Your using-declaration causes name lookup to succeed where it would otherwise fail, that is, it tells the compiler where to find the function f. But it does not tell it which A subobject f acts on, that is, which one will be passed as the implicit this parameter when f is called.
There is only a single function A::f even though there are two A subobjects of C, and it takes an implicit this argument of type A*. In order to call it on a C object, C* must be implicitly converted to A*. This is always ambiguous, and is not affected by any using-declarations.
(This makes more sense if you put data members inside A. Then C would have two of each such data member. When f is called, if it accesses data members, does it access the ones in the A subobject inherited from B1, or the ones in the A subobject inherited from B2?)
There's a note in [namespace.udecl]/p17 that addresses this situation directly:
[ Note: Because a using-declaration designates a base class member
(and not a member subobject or a member function of a base class
subobject), a using-declaration cannot be used to resolve inherited
member ambiguities. For example,
struct A { int x(); };
struct B : A { };
struct C : A {
using A::x;
int x(int);
};
struct D : B, C {
using C::x;
int x(double);
};
int f(D* d) {
return d->x(); // ambiguous: B::x or C::x
}
—end note ]
In addition to T.C.'s answer, I'd like to add that the name lookup in derived class is explained in the standard pretty much in detail in section 10.2.
Here what is said about processing of using-declarations :
10.2/3: The lookup set (...) consists of two component sets: the declaration set, a set of members named f; and the subobject set, a set of subobjects where declarations of these members (possibly including
using-declarations) were found. In the declaration set, using-declarations are replaced by the members they designate, and type declarations (including
injected-class-names) are replaced by the types they designate.
So when you try to declare in struct C
using B1::f; // you hope to make clear that B1::f is to be used
according to the lookup rules, your compiler nevertheless finds the possible candidates: B1::f and B2::f so that it's still ambiguous.

C++11 use variadic subclass when they are template [duplicate]

The following snippet produces an "ambigious call to foo" error during compilation, and I'd like to know if there is any way around this problem without fully qualifying the call to foo:
#include <iostream>
struct Base1{
void foo(int){
}
};
struct Base2{
void foo(float){
}
};
struct Derived : public Base1, public Base2{
};
int main(){
Derived d;
d.foo(5);
std::cin.get();
return 0;
}
So, question is as the title says. Ideas? I mean, the following works flawlessly:
#include <iostream>
struct Base{
void foo(int){
}
};
struct Derived : public Base{
void foo(float){
}
};
int main(){
Derived d;
d.foo(5);
std::cin.get();
return 0;
}
Member lookup rules are defined in Section 10.2/2
The following steps define the result of name lookup in a class scope, C. First, every declaration for the name in the class and in each of its base class sub-objects is considered. A member name f in one sub-object B hides a member name f in a sub-object A if A is a base class sub-object of B. Any declarations that are so hidden are eliminated from consideration. Each of these declarations that was introduced by a using-declaration is considered to be from each sub-object of C that is of the type containing the declara-tion designated by the using-declaration. If the resulting set of declarations are not all from sub-objects of the same type, or the set has a nonstatic member and includes members from distinct sub-objects, there is an ambiguity and the program is ill-formed. Otherwise that set is the result of the lookup.
class A {
public:
int f(int);
};
class B {
public:
int f();
};
class C : public A, public B {};
int main()
{
C c;
c.f(); // ambiguous
}
So you can use the using declarations A::f and B::f to resolve that ambiguity
class C : public A, public B {
using A::f;
using B::f;
};
int main()
{
C c;
c.f(); // fine
}
The second code works flawlessly because void foo(float) is inside C's scope. Actually d.foo(5); calls void foo(float) and not the int version.
Name lookup is a separate phase to overload resolution.
Name lookup occurs first. That is the process of deciding which scope the name applies to. In this case we must decide whether d.foo means d.D::foo, or d.B1::foo, or d.B2::foo. The name lookup rules do not take into account function parameters or anything; it is purely about names and scopes.
Only once that decision has been made, do we then perform overload resolution on the different overloads of the function in the scope where the name was found.
In your example, calling d.foo() would find D::foo() if there were such a function. But there is none. So, working backwards up the scopes, it tries the base classes. Now foo could equally look up to B1::foo or B2::foo so it is ambiguous.
For the same reason, you would get ambiguity calling unqualified foo(5); inside a D member function.
The effect of the recommended solution:
struct Derived : public Base1, public Base2{
using Base1::foo;
using Base2::foo;
is that this creates the name D::foo, and makes it identify two functions. The result is that d.foo resolves to d.D::foo, and then overload resolution can happen on these two functions that are identified by D::foo.
Note: In this example D::foo(int) and Base1::foo(int) are two identifiers for the one function; but in general, for the name lookup and overload resolution process, it doesn't make a difference whether they are two separate functions or not.
Will it work for you?
struct Derived : public Base1, public Base2{
using Base2::foo;}

Access modifier's different behaviors in inheritance depend on "this" keyword and templates or lack thereof

I want to understand the access modifiers' 4 different behaviors regarding inheritance when it comes to the 4 combinations of using and/or omitting templates and the this keyword. All following code is done in g++ 4.8:
Here's a GrandChild class, which privately inherits from Parent, which privately inherits from GrandParent, which has a public enum n. Non-object, client code can access GrandParent::n, because the latter is a public enum. But GrandParent::n is inaccessible from within GrandChild:
#include <iostream>
using namespace std;
struct GrandParent { enum {n = 0}; };
struct Parent : private GrandParent { enum {n = 1}; };
struct GrandChild : private Parent {
enum {n = 2};
void f() {cout << GrandParent::n << endl;}
// ^ error: 'struct GrandParent GrandParent::GrandParent'
// is inaccessible
};
int main() {
cout << GrandParent::n << endl;
// ^ non-object access would have outputted `0` had `GrandChild`'s
// definition compiled or been commented out.
}
1.) Is GrandParent::n's inaccessibility from within GrandChild caused by GrandChild's possession of a GrandParent base subobject, which hides non-object access to GrandParent::num, and whose 2-generational privateness makes the base subobject’s n also inaccessible? I'd expected the error message to be about that.
2.) But apparently, it isn't. Why does the error complain about GrandParent's constructor?
3.) Prepending this-> to GrandParent::n in f()'s definition will add the error I expected in #1 but won't remove the ctor complaint. Why? I assumed that including this-> is redundant and that its omission will cause the lookup to attempt to find the n of the GrandParent subobject within GrandChild's scope before the less-immediately-scoped non-object n anyway.
4.) Why does this template variant compile? It seems functionally similar to the non-template one:
#include <iostream>
using namespace std;
template <unsigned int N>
struct bar : private bar<N - 1> {
enum {num = N};
void g() {
static_assert(N >= 2, "range error");
cout << bar<N - 2>::num << endl;
}
};
template <>
struct bar<0> { enum {num = 0}; };
int main() {
bar<2> b2;
b2.g(); // Output: 0
}
5.) Prepending this-> to bar<N - 2>::num in g()'s definition causes the compiler error I expected in #1 only. But why doesn't it include the error of #2? And why doesn't its omission yield #2's error?
The whole issue here is name lookup (I think this also has been the case in one of your previous questions). I'll try to illustrate my understanding of what's happening:
Every (named) class gets an injected-class-name. For example:
struct GrandParent
{
// using GrandParent = ::GrandParent;
enum {n = 0};
};
You can use this injected-class-name to refer to the class itself. It is not that useful for ordinary classes (where unqualified lookup could find the name GrandParent in the surrounding scope anyway), but for derived classes and class templates:
namespace A
{
struct Foo
{
// using Foo = ::A::Foo;
};
};
struct Bar : A::Foo
{
void woof(Foo); // using the injected-class-name `::A::Foo::Foo`
};
template<class T, int N, bool b>
struct my_template
{
// using my_template = ::my_template<T, N, b>;
void meow(my_template); // using the injected-class-name
};
This isn't inheritance as in "it's part of the base class subobject", but the way unqualified lookup is specified: If the name isn't found in the current class' scope, the base class scopes will be searched.
Now, for the first (non-template) example in the OP:
struct Parent : private GrandParent
{
// using Parent = ::Parent;
enum {n = 1}; // hides GrandParent::n
};
struct GrandChild : private Parent {
// using GrandChild = ::GrandChild;
enum {n = 2};
void f() {cout << GrandParent::n << endl;}
// ^ error: 'struct GrandParent GrandParent::GrandParent'
// is inaccessible
};
Here, the expression GrandParent::n invokes unqualified name lookup of the name GrandParent. As unqualified lookup stops when the name is found (and doesn't consider surrounding scopes), it will find the injected-class-name GrandParent::GrandParent. That is, lookup searches the scope of GrandChild (name not found), then the scope of Parent (name not found) and finally the scope of GrandParent (where it finds the injected-class-name). This is done before and independent of access checking.
After the name GrandParent has been found, accessibility is checked eventually. Name lookup required to go from Parent to GrandParent to find the name. This path is blocked for anyone but members and friends of Parent, as the inheritance is private. (You can see through that path, but you may not use it; visibility and accessibility are orthogonal concepts.)
Here's the standardese [basic.lookup.unqual]/8:
For the members of a class X, a name used in a member function body [...] shall be declared in one of the following ways:
before its use in the block in which it is used or in an enclosing block, or
shall be a member of class X or be a member of a base class of X, or
if X is a nested class of class Y [...]
[...]
if X is a member of namespace N, or [...], before the use of the name,
in namespace N or in one of N’s enclosing namespaces.
Name lookup in base classes is rather complicated as multiple base classes might have to be considered. For single inheritance and a member looked up in the scope of a member function body, it starts with the class which this function is a member of, and then traverses the base classes up (base, base of base, base of base of base, ..). See [class.member.lookup]
The template case is different, as bar is the name of a class template:
template <unsigned int N>
struct bar : private bar<N - 1> {
enum {num = N};
void g() {
static_assert(N >= 2, "range error");
cout << bar<N - 2>::num << endl;
}
};
Here, bar<N - 2> is used. It is a dependent name, as N is a template parameter. Name lookup is therefore postponed until the point of instantiation of g. The specialization bar<0> can be found, even it is declared after the function.
The injected-class-name of bar can be used as a template-name (referring to the class template) or as a type-name (referring to the current instantiation) [temp.local]/1:
Like normal (non-template) classes, class templates have an injected-class-name (Clause 9). The injected-
class-name can be used as a template-name or a type-name. When it is used with a template-argument-list,
as a template-argument for a template template-parameter, or as the final identifier in the elaborated-type-
specifier of a friend class template declaration, it refers to the class template itself. Otherwise, it is equivalent
to the template-name followed by the template-parameters of the class template enclosed in <>.
That is, bar<N - 2> finds bar as the injected-class-name of the current class (instantiation). As it is used with a template-argument-list, it refers to another, unrelated specialization of bar. The injected-class-name of the base class is hidden.
bar<0>::num is accessed not through an access path that goes through a private inheritance, but directly through the injected-class-name of the current class, referring to the class template itself. num being a public member of bar<0> is accessible.
For a good explanation of why private inheritance is not like public and protected inheritance, see two good answers from private inheritance.
From a common understanding of inheritance, C++’ “private inheritance”
is a horrible misnomer: it is not inheritance (as far as everything
outside of the class is concerned) but a complete implementation
detail of the class.
Seen from the outside, private inheritance is actually pretty much the
same as composition. Only on the inside of the class do you get
special syntax that is more reminiscent of inheritance than
composition.
There’s a caveat though: C++ syntactically treats this as inheritance,
with all the benefits and problems that this entails, such as scope
visibility and accessibility. Furthermore, C-style casts (but no C++
cast!) actually ignores visibility and thus succeeds in casting your
Derived pointer to Base:
Base* bPtr = (Base*) new Derived();
Needless to say, this is evil.
Public inheritance means that everyone knows that Derived is derived
from Base.
Protected inheritance means that only Derived, friends of Derived, and
classes derived from Derived know that Derived is derived from Base.*
Private inheritance means that only Derived and friends of Derived
know that Derived is derived from Base.
Since you have used private inheritance, your main() function has no
clue about the derivation from base, hence can't assign the pointer.
Private inheritance is usually used to fulfill the
"is-implemented-in-terms-of" relationship. One example might be that
Base exposes a virtual function that you need to override -- and thus
must be inherited from -- but you don't want clients to know that you
have that inheritance relationship.
As well as Inaccessible type due to private inheritance.
This is due to the injected class name from A hiding the global A
inside C. Although A is visible, it is not accessible (since it is
imported as private), hence the error. You can access A by looking it
up in the global namespace:
void foo(::A const& a) {}
So for example, this will work:
class GrandChild;
struct GrandParent { enum {n = 0}; };
struct Parent : private GrandParent {
enum {n = 1};
friend GrandChild;
};
struct GrandChild : private Parent {
void f() {cout << GrandParent::n << endl;}
};
Otherwise you need to use global scope or the using directive to bring ::GrandParent into scope.

Having a class static method with same name as another class

Here is the example :
struct A
{
A(const int a ):b(a)
{
}
int b;
};
struct B
{
B() : a(5)
{
}
static void A()
{
}
A a;
};
int main()
{
B::A();
}
And the compiler error is :
a9.cpp:19: error: ‘A’ does not name a type
a9.cpp: In constructor ‘B::B()’:
a9.cpp:24: error: class ‘B’ does not have any field named ‘a’
I am using gcc 4.3.0 on fedora 9.
Can someone explains why is the compiler complaining?
If possible, with references from the standard.
Thanks
This works:
struct B {
B() : a(5) { }
static void A() { }
::A a;
};
Since you've used A as a member name in B, that member's definition shadows the A type from the outer namespace. Using :: you can get to that namespace.
This behavior is specified in the (draft) standard as:
3.3.7 (1) "A name can be hidden by an explicit declaration of that same name in a nested declarative region" (the definition of struct B, which is nested in the namespace where struct A is also defined).
Carefully read the introduction to chapter 3, Basic concepts, for further clarification. Especially, this section specifies that
3 (7) Two names are the same if
they are identifiers composed of the same character sequence; or
they are the names of overloaded operator functions formed with the same operator; or
they are the names of user-defined conversion functions formed with the same type.
Note that this last definition does not distinguish between types and class members, so the name hiding (shadowing) rule 3.3.7 (1) applies.