I know I can do
class Foo;
and probably
struct Bar;
and global functions
bool IsValid(int iVal);
What about a typed enum? What about a typed enum within an undeclared class? What about a function with an undeclared class? What about a static member within an undeclared class? What about these within an unknown namespace? Am I missing anything else that can be forward declared?
You can forward declare
Templates, including partial specializations
Explicit specializations
Nested classes (this includes structs, "real" classes and unions)
Non-nested and local classes
Variables ("extern int a;")
Functions
If by "forward declaration" you strictly mean "declare but not define" you can also forward declare member functions. But you cannot redeclare them in their class definition once they are declared. You cannot forward-declare enumerations. I'm not sure whether I missed something.
Please note that all forward declarations listed above, except partial and explicit specializations, need to be declared using an unqualified name and that member functions and nested classes can only be declared-but-not-defined in their class definition.
class A { };
class A::B; // not legal
namespace A { }
void A::f(); // not legal
namespace A { void f(); } // legal
class B { class C; }; // legal
class B::C; // declaration-only not legal
class D { template<typename T> class E; };
template<typename T> class D::E<T*>; // legal (c.f. 14.5.4/6)
Related
Inside a function one can employ the using declaration to import a name in the current scope, like
namespace A {
int y;
}
void f() { using A::y; }
A using declaration can be used in a class definition, to alter the accessibility of an inherited member, but also it is useful to explicitly bring a member inherited from a template class
template <bool activate>
struct A {
int x;
};
template <bool activate>
struct B : public A<activate> {
using A<activate>::x;
};
This is particularly useful, as it avoids the need to access to x via this->x or A<activate>::x. This can be used only inside the body of the definition, but not inside a member function.
template <bool activate>
struct A {
int x;
};
template <bool activate>
struct B : public A<activate> {
int f() const noexcept {
// This gives: "error: using-declaration for member at non-class scope"
// using A<activate>::x;
return x;
}
};
Is there a rationale for this restriction of the language, that is, for the fact that using A<activate>::x can only be placed inside the definition of the class?
Absent a direct statement on the subject in Design & Evolution of C++, it’s hard to reliably infer intent for something like this. That said, until recently, the standard described using-declarations as introducing declarations as synonyms for the named declarations. In that view, it would be more than a little strange to have a member declaration belong to a block scope. Now they are considered to be redirects that are replaced by their referents during name lookup, which would be more consistent with this notional usage.
I just read this answer, and it completely puzzles me.
I was always thinking a class declaration can appear many times, and only the definition has to exist only once, like:
/*class Class {*/
class A; // (1) forward declaration
class A { // (2) definition, only once
int m;
};
class A; // (3) declaration again, legal?
class A a; // (4) declaration again, legal?
/*};*/
From the linked answer: (3) (and (4)?) is illegal if the code above is nested inside a class (definition and declarations of class A are nested inside class Class).
On cppreference, I found an example of the above, not nested:
struct s { int a; };
struct s; // does nothing (s already defined in this scope)
void g() {
struct s; // forward declaration of a new, local struct "s"
// this hides global struct s until the end of this block
s* p; // pointer to local struct s
struct s { char* p; }; // definitions of the local struct s
}
See the second line.
Question: Given that it is illegal inside a class, is my example code, and the cppreference example above, legal when not nested inside a class? Or more generally: When can a class declaration follow a definition (how is it inside namespaces for example)? If it is legal, why is there a difference?
From [basic.def]:
A declaration (Clause 7) may introduce one or more names into a translation unit or redeclare names introduced by previous declarations.
From [class.name]:
A declaration consisting solely of class-key identifier; is either a redeclaration of the name in the current scope or a forward declaration of the identifier as a class name. It introduces the class name
into the current scope.
So it's generally legal to do this. There's just the one exception in [class.mem]:
A member shall not be declared twice in the member-specification,
except that a nested class or member class template can be declared and then later defined, and except that an enumeration can be introduced with an opaque-enum-declaration and later redeclared with an enum-specifier.
Perfectly OK in namespace scope, not allowed in class scope.
As to why? Well, this rule let's you "forward" declare all the classes you need everywhere you would typically be allowed to do so:
// a.h
struct C;
struct A {
C* c;
};
// b.h
struct C;
struct B {
C& c;
};
without having to worry about somebody actually including the full declaration and breaking everything for you:
// d.h
#include "c.h"
#include "a.h" // now C was already declared!
#include "b.h" // and here too!
struct D { ... };
This isn't so much of a concern within a class definition. It can't exactly span multiple files. So the inability to redeclare nested types doesn't actually achieve anything.
class A; This is a forward declaration of incomplete class A (legal).
class A { int m; }; This is the definition of Class A (legal).
class A; This is re-declaration of class A (legal).
class A a; This is declaration of object a of type A (legal).
Is there any way to redeclare a class to define methods which where only declared this far?
Eg. something like:
class A
{
void a();
void b() {}
}
class A
{
void a() {}
}
instead of
class A
{
void a();
void b() {}
}
A::a() {}
The reason is I created a lot of code with methods defined inside the class defintion, without using headers. I do not had cyclic references up to now, but recently there is need to. I don't like to define bunches of methods by the Type::method syntax, as only very few methods have to be known before the latter definition of the class.
So I like somewhat like a backward declaration, declare or define only a few methods before for cyclic references and define the whole class later.
No, there is no way to redefine a class.
According to the C++ language standard the class definitions is:
class-specifier:
class-head { member-specification_opt }
The standard explicitly says that member specification should be complete within class definition:
Members of a class are data members, member functions (9.3), nested types, and enumerators. The member-specification in a class definition declares the full set of members of the class; no member can be added elsewhere.
Also the standard gives example of redefinition of class:
struct S { int a; };
struct S { int a; }; // error, double definition
is ill-formed because it defines S twice.
Unfortunately there is no way to declare the class again once it is Closed with }.
Only thing you can do is you can inherit and define the method.
class B : public A { a() {} } ;
I have a situation where I want to hide a base class and limit the classes that can inherit from it:
namespace _detail {
class Private abstract final {
struct Base abstract {
protected:
Base() {}
};
friend struct ::A;
friend struct ::B;
friend struct ::C;
};
}
struct A : _detail::Private::Base {}; //error
struct B : _detail::Private::Base {}; //error
struct C : _detail::Private::Base {}; //error
The compiler tells me that _detail::Private::Base is inaccessible to A, B and C even though they are friends with Private. I've used this sort of pattern before without an issue, and can't really see what's different here compared to the other times I've used it. What am I not seeing?
C++ language does not allow you to use qualified names (like ::A) in friend declarations, unless these qualified names refer to previously declared entities. Actually, this rule is applied virtualy everywhere, not only in friend declarations: qualified names have to refer to previously declared entities.
In your case you used qualified name ::A in friend declaration friend struct ::A. For that to work, struct A from global namespace has to be known to the compiler beforehand. In your case A is not declared at that point, which makes friend struct ::A declaration ill-formed. It should not even compile by formal rules of the language.
If your compiler accepts this, you have to consult your compiler documentatuion to figure out what it means. I suspect that friend struct ::A for unknown ::A is interpreted as equivalent to friend struct A, i.e. it declares _detail::A as friend.
If you make a forward declaration struct A; before declaring namespace _detail, it might make it work as intended.
I understand that the member names of a base-class template are hidden within the scope of a derived class, and therefore must be accessed using this->foo or Base<T>::foo. However, I recall that C++ also allows you to use the using keyword, which can come in handy in a derived-class function which frequently accesses a base-class variable. So, in order to avoid cluttering up the function with this-> everywhere, I'd like to use the using keyword.
I know I've done this before, but for whatever reason I can't get it to work now. I'm probably just doing something stupid, but the following code won't compile:
template <class T>
struct Base
{
int x;
};
template <class T>
struct Derived : public Base<T>
{
void dosomething()
{
using Base<T>::x; // gives compiler error
x = 0;
}
};
int main()
{
Derived<int> d;
}
The error, (with GCC 4.3) is: error: ‘Base<T>’ is not a namespace
Why doesn't this work?
It doesn't work because C++ language has no such feature and never had. A using-declaration for a class member must be a member declaration. This means that you can only use in class scope, but never in local scope. This all has absolutely nothing to do with templates.
In other words, you can place your using-declaration into class scope
struct Derived : public Base<T> {
...
using Base<T>::x;
...
};
but you can't have it inside a function.
Using-declarations for namespace members can be placed in local scope, but using-declarations for class members cannot be. This is why the error message complains about Base<T> not being a namespace.
Outside class scope (if you are in a block etc), you can only name namespace members in a using declaration.
If you don't want to place that using declaration into the scope of Derived (which IMO is the favorable solution), your other option is to use a reference
int &x = this->x;
x = 0;
It should be noted that this is semantically different, because it
Forces a definition to exist for Base<T>::x, which might not be the case for static const data members
Forces Base<T>::x to be of type int& or be convertible to type int&.
Otherwise, if you want to avoid using this-> all again, I don't see other options.
template <class T>
struct Base
{
int x;
};
template <class T>
struct Derived : public Base<T>
{
using Base<T>::x;
void dosomething()
{
x = 0;
}
};
int main()
{
Derived<int> d;
}
As others said, it is working only class scope.