I am using visual studio 2010, and can't quite get, how is this class wrong (syntax error : identifier 'EnumType ') and won't compile:
class BrokenClassWithEnum
{
private:
void useEnum (EnumType enumType); //syntax error : identifier 'EnumType '
public:
enum EnumType
{
VAL1,
VAL2,
VAL3
};
}
And this is OK:
class WorkingClassWithEnum
{
public:
enum EnumType
{
VAL1,
VAL2,
VAL3
};
private:
void useEnum (EnumType enumType);
}
What happened to the class scope?
I don't think the order of definition (not declaration) matters but a forward declaration will resolve this error - at least in MSVC++ 6. Outside of MSVC++ 6 you should specify a storage type to forward declare an enum (the requirement for specifying the storage type in a forward enum was in the C++0x standard)
NOTE: VC++ 6 will allow the storage type to be omitted, but if you are forward declaring an enum, you should declare the storage type (SEE BELOW):
This will resolve the error in VC++6. However, VC++6 does not appear to support a STORAGE TYPE for an enum inside a class as required by the C++0x standard:
class BrokenClassWithEnum {
public:
enum EnumType;
private:
void useEnum (EnumType enumType);
public:
enum EnumType {
VAL1,
VAL2,
VAL3
};
};
Normally I.E. within a C++0x compliant compiler you would use something like:
class BrokenClassWithEnum {
public:
enum EnumType : int;
private:
void useEnum (EnumType enumType);
public:
enum EnumType : int {
VAL1,
VAL2,
VAL3
};
};
NOTE:Forward declaration of enums is possible in some but not all C++ versions:
Forward declaring an enum in c++
In C++ any referenced non-built-in name must have been declared somewhere earlier.
It might appear that this rule has an exception for class definitions, because the following works fine:
struct S
{
void foo() { cout << x_ << endl; }
int x_;
S(): x_( 42 ) {}
};
However, the rule about declaration-before-use applies to the transformed code
struct S
{
inline void foo();
int x_;
inline S();
};
void S::foo() { cout << x_ << endl; }
S::S() : x_( 42 ) {}
which is what the compiler "proper" sees. And here there is no use of anything that hasn't already been declared.
The proper C++03 solution to your problem is to define the enumeration type before its first use. With C++11 you can alternatively forward-declare it, but then an underlying type must be specified,
C++11 §7.2/3:
“An opaque-enum-declaration is either a redeclaration of an enumeration in the current scope or a declaration
of a new enumeration. [Note: An enumeration declared by an opaque-enum-declaration has fixed underlying
type and is a complete type. The list of enumerators can be provided in a later redeclaration with an enum-
specifier. —end note ] A scoped enumeration shall not be later redeclared as unscoped or with a different
underlying type. An unscoped enumeration shall not be later redeclared as scoped and each redeclaration
shall include an enum-base specifying the same underlying type as in the original declaration.”
Within the class definition itself, items must appear in order (with dependent items appearing before the items that depend on them) like they do at any other scope. Inside a class method body (even if inlined) the entire definition of the class is available.
I believe member variables can be accessed before declarations within the class because class validation or compilation is done in two pass.
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.
The STL <memory> header (MSVC implementation) contains a class called:
template <class _Ty> class _Ref_count_obj2 : public _Ref_count_base
This class has a member:
union {
_Wrap<_Ty> _Storage;
};
where _Wrap is defined as:
template <class _Ty>
struct _Wrap {
_Ty _Value; // workaround for "T^ is not allowed in a union"
};
From my understanding, this code is designed to hold an object of type _Ty following its construction via the new operator. However I can't figure out why this was done; it seems like using a struct instead of a struct inside a union would work just as well.
Can anyone explain the reasoning behind this? Also, can anyone explain the comment in the _Wrap definition?
First, embedding the _Storage member in a union will prevent default destruction of that object (which is, more than likely, a non-trivial type); this appears to be essential, as the class involved is a reference counter. (By default, unions have a deleted destructor; see, for example: Is a Union Member's Destructor Called .)
Second, using an anonymous union 'moves' the _Storage identifier into the enclosing scope, thus removing any need for X.-style notation (if the union were to be named X). From cppreference:
Members of an anonymous union are injected in the enclosing scope (and
must not conflict with other names declared there).
Last, the need to wrap the union's member into a templated structure is so that the class will work with reference types, which are not allowed in unions. To check this last part out, try the following code with the commented-out lines made active:
template <class _Ty>
struct _Wrap {
_Ty _Value; // workaround for "T^ is not allowed in a union"
};
template<class T>
class bob {
public:
bob(T t) : uncle{t}//, aunty(t)
{
}
private:
union {
_Wrap<T> uncle;
};
// union {
// T aunty;
// };
};
int main()
{
int i = 42;
bob<int&> b{ i }; // Note: Template uses a REFERENCE type
return 0;
}
Consider the following code. I was assuming that by having the type of the strongly typed enum specified that I would be able to use it to pass to functions and templates of the same type since the specified underlying type is the same; although the compiler complains that the cast to the type is missing. In the code below removing the keyword class and the specifier on the enum of Test::TOTAL_ITEMS back to TOTAL_ITEMS will work. I understand that they don't want any type conversions for strongly typed enums but when the underlying type is the same as the type that is expected to be received by the function or template I would expect the compiler to not complain about this and not force a specific cast. Thoughts?
#include <iostream>
#include <cstdint>
template <typename T, std::size_t N = 10>
class Y {
public:
Y() : z_() {
}
~Y() = default;
private:
T z_[N];
};
class X {
public:
enum class Test : std::size_t {
ITEM1 = 0,
ITEM2,
TOTAL_ITEMS,
};
private:
Y<int, Test::TOTAL_ITEMS> collection;
};
int main() {
X xx;
}
The whole purpose of scoped enumerations is to prevent implicit conversions to the underlying type. You'll need to cast it to get your code to compile
#include <type_traits>
Y<int, static_cast<std::underlying_type<Test>::type>(Test::TOTAL_ITEMS)> collection;
Or, if all you care about is specifying an underlying type for your enum, then drop the class keyword from its definition, and your code will compile as is.
enum Test : std::size_t {
// ...
};
The purpose of enum class is to keep its instances from implicitly casting to some other type. This is why removing class compiles: regular enum instances implicitly cast to anything their underlying type can.
When you want to convert an enum class to some other type, you must do so explicitly:
enum class Foo : int { FEE, FYE, FOE, FUM };
void f(Foo x) {};
void g(int x) {};
int main()
{
f(Foo::FEE); // Okay: correct type
//f(0); // Error: no implicit conversion
f(static_cast<Foo>(0)); // Okay: explicitly converted
//g(Foo::FYE); // Error: no implicit conversion
g(1); // Okay: correct type
g(static_cast<int>(Foo::FYE)); // Okay: explicitly converted
}
Live demo. See std::underlying_type for when you'd like to programatically extract a type.
I need to access a public enum belonging to another class, to simplify, something like this:
class obj
{
public:
enum Type
{
t1,
t2,
t3
};
Type type;
};
class otherObj
{
public:
void setType(obj* o);
};
void otherObj::setType(obj* o)
{
o->type = obj::Type::t1;
return;
}
How do I do that, because the line
o->type = obj::Type::t1;
throws out an error:
obj::Type is not a class or namespace.
obj::t1
obj::t2
obj::t3
Aren't C++ enums great? The values fall into the scope above them even though the enum can be treated as a type.
You either just use
obj::t1;
or specify the class attribute with your enum declaration
enum class Type {
t1,
t2,
t3
};
In C++03, the enum values belong to the enclosing scope. Hence, replacing obj::Type::t1 with obj::t1 would work for you.
This is somewhat counter-intuitive, and is addressed by the enum class feature in C++11, which puts the enum values directly in the enum scope. Thus, if you use enum class in a C++11 compliant compiler, then you would be able to use obj::Type::t1 as you are currently doing.
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.