I did a mistake in my program, I wrote
struct vector<int> v;
instead of
vector<int> v;
but it seems that the compiler doesn't care: http://codepad.org/TCPb8p2u
Why does it work? Is there some differencies with or without struct?
If you write class, it would also work.
class vector<int> v;
See this: http://www.ideone.com/EoJxk
This is actually old C style. The C++ Standard calls it elaborated-type-specifier in section §3.4.4.
The keyword struct (or class, enum) is sometimes used to remove ambiguities, or to make hidden names visible to the compiler. Consider the following example from the Standard itself (from section §9.1/2). Please notice that there exists a struct with name stat and with exactly same also exists a function:
struct stat {
// ...
};
stat gstat; // use plain stat to define variable
int stat(struct stat*); // redeclare stat as function
void f()
{
struct stat* ps; // struct prefix needed to name struct stat
// ...
stat(ps); //call stat()
// ...
}
§9.1/2 says,
A class definition introduces the
class name into the scope where it is
defined and hides any class, object,
function, or other declaration of that
name in an enclosing scope (3.3). If a
class name is declared in a scope
where an object, function, or
enumerator of the same name is also
declared, then when both declarations
are in scope, the class can be
referred to only using an
elaborated-type-specifier (3.4.4).
This is a feature of C++ that's used to resolve ambiguity between a variable and type with the same name. I believe they're called 'elaborate type specifiers.'
You can use a keyword to tell the compiler exactly what you mean, when there would normally be ambiguity.
Take this for example:
int x = 0;
class x { };
// Compiler error! Am I refering to the variable or class x?
x y;
// This is okay, I'm telling the compiler which x I'm referring to.
class x y;
This can also be used to specify enums and unions, not just structs and classes, though you can only have one user-defined type with the same name.
The others have already explained it that what you uses is called elaborated type specifier, which can be used for name unhiding and ambiguity resolution.
However, what also works here is one curious feature of C++ language, which states that class-key (i.e. class or struct keyword) used in class declaration is not required to agree with the class-key used in the elaborated type specifier. E.g. you can declare your class with class keyword and then later refer to it with struct keyword (and vice versa). There's no error in it
class S {};
int main() {
struct S s; // OK, 's' has type `S` (i.e. `class S`)
}
Standard std::vector template class is declared with keyword class, but there's no error in referring to it as struct std::vector, which is what you did in your example.
And no, it makes no difference whether in your declaration of v you use class, struct or nothing at all.
Related
I found the following code in a header file and the "BOOT" class is defined in another header file.
class BOOT* boot(void);
It looks like a declaration of a function, but it begins with class.
This is an elaborated type specifier:
Elaborated type specifiers may be used to refer to a previously-declared class name (class, struct, or union) or to a previously-declared enum name even if the name was hidden by a non-type declaration. They may also be used to declare new class names.
https://en.cppreference.com/w/cpp/language/elaborated_type_specifier
Taking from answers of Artefacto and dfrib because it brings it on point: It is equivalent to:
class BOOT;
BOOT* boot(void);
In your example it essentially does a forward declaration of the class BOOT if it is not known yet. See this example struct Data* Data; from the same page:
struct Node {
struct Node* Next; // OK: lookup of Node finds the injected-class-name
struct Data* Data; // OK: declares type Data at global scope
// and also declares the data member Data
friend class ::List; // error: cannot introduce a qualified name
enum Kind* kind; // error: cannot introduce an enum
};
Data* p; // OK: struct Data has been declared
It is the same as this:
class BOOT;
BOOT* boot(void);
So it's a pointer to class BOOT, but with a declaration of the class as well. The class need not be defined at this point.
What does “class classname* funcname(void) ”mean in C++?
It is a function declaration.
It looks like a declaration of a function, but it begins with "class".
class classname* is the return type of the function. class classname is an elaborated type specifier.
Different forms of forward declarations used to introduce class-name:s into its scope
In C++ you may declare a function type whose return type contains a class type that is defined elsewhere, as long as you either explicitly forward declare the class type prior to the function declaration:
class BOOT;
BOOT* boot();
but you may likewise place the forward declaration in-line in the function declaration:
class BOOT* boot();
This is one of the places where, possibly somewhat unexpectedly, forward declarations can be used. Another example is as in the template argument list for a type-template parameter:
template<typename T>
struct Identity { using type = T; };
using IdentityBoot = Identity<struct BOOT>;
// ^^^^^^^^^^^ also a forward declaration
// OK
BOOT* boot();
// OK
typename IdentityBoot::type* another_boot();
Elaborated type specifiers can be used to introduce names into its scope
Formally, it's an elaborated-type-specifier, governed by [dcl.type.elab],
elaborated-type-specifier:
class-key [...]
[...]
that is used to, as per [class]/1, make a class-name that is introduced into the scope where the elaborated-type-specifier is used [emphasis mine]:
A class is a type. Its name becomes a class-name ([class.name]) within its scope. [...]
Class-specifiers and elaborated-type-specifiers are used to make class-names.
So as I understand it, when I see double colons(abc::xyz) used the thing on the left is a namespace and the thing on the right can be a function or variable of some sort that is defined in that namespace. ex. namespace::bar, namespace::foo()
Now, can the thing on the left be a class? ex. class::bar, class::foo()
If so, does anyone have any info on this. I can find lots of info of scope resolution pertaining to namespaces but not when it comes to classes.
In my situation I am going through a rather large project of code that is from another individual.
The code usage that I am trying to understand is that I have the following line of code...
multi_img::ptr input = imginput::ImgInput(config.input).execute();
On the right the imginput::ImgInput() can be found because there is a namespace imginput that I can find. But on the left, the multi_img::ptr, there is no multi_img namespace in the project. There is a multi_img class that contains the following line...
typedef boost::shared_ptr<multi_img> ptr;
I believe this is what multi_img::ptr means but can not find any documentation to back up my assumption.
Now, can the thing on the left be a class?
Yes it can, and to justify consider the following example:
#include <iostream>
class foo {
public:
void fun() const { std::cout << "foo:fun()" << std::endl; }
};
int main() {
foo f;
f.foo::fun();
return 0;
}
DEMO
Every class member lies in the scope of its class.
Edit after #Cheersandhth.-Alf constructive comment:
Thus, you can access a member through an object with either the classical way (e.g., f.fun()) in which case you'll have a virtual call or you call it like in the example (i.e., f.foo::fun()) in which case you explicitly disambiguate the scope of member function at compile time.
Yes, you can have a class name on the left of ::. It is used to denote a member of that class. The multi_img class has a member called ptr. As you have shown, that member is a typedef. That is, the type multi_img::ptr is a synonym of boost::shared_ptr<multi_img>.
Note that :: is used to access static members and nested types, since these only require the name of the class and not a particular object that of that class type. We use . and -> to access non-static data members of a particular object.
Usually the classname::member notation is used to
Access static members.
E.g. Blah::uuid.
Prevent virtual call.
E.g. in Blah::foo, a call like Base::foo().
Disambiguate.
E.g. with two bases A and B, both of which provides a foo, a call like B::foo().
Some older libraries use classes instead of namespaces. I vaguely recall an XML library and a GUI library. Not sure which.
Personally I do the class-as-faux-namespace for enumeration types, e.g.
struct Weekdays
: Non_instantiable
{
enum Enum { wednesday, friday, saturday };
};
used like
auto foo() -> Weekdays::Enum { return Weekdays::friday; }
even after C++11 started supported enum class.
Sometimed it is difficult to know whether the nested name specifier denotes a namespace or a class because the syntax is the same. Moreother the same name can denote either a namespace or a class depending on the declaration region where the name is used. For example
namespace A
{
struct A
{
static int a;
static int b;
static int c;
};
int A::a = 5;
}
int A::A::b = 10;
int A::A::c = a;
The most appropriate documentation is the C++ Standard. You may download a working draft of the Standard from the ISO-IEC site
As for the typedef that defines a type
typedef boost::shared_ptr<multi_img> ptr;
then it seems that it is defined in the class definition of multi_img. So if the name is used outside the class scope it shall be qualified
multi_img::ptr input = imginput::ImgInput(config.input).execute();
I often see C++ code like this:
void foo()
{
struct sockaddr* from;
// ...
}
Why is the struct specifier needed? Does it actually do anything? The compiler can already know that sockaddr is declared as a struct, so I wonder why this is useful or necessary.
I've tried removing it in the past and haven't noticed a difference in behaviour, but I'm not confident it's safe to remove.
Similarly, what's the difference between these two?
sizeof(struct sockaddr)
sizeof(sockaddr)
As a coding "style", this is most likely a heritage of C, where the keyword is necessary.
In C++ this is not needed in most situations, although it is used sometimes to force the compiler to resolve a name to the name of a type rather than the name of some other entity (like a variable, as in the following example):
struct x
{
};
int main()
{
int x = 42;
struct x* pX = nullptr; // Would give a compiler error without struct
}
Personally, I do not consider good style having a variable, or a function with the same name as a type, and I prefer avoiding having to use the struct keyword for this purpose at all, but the language allows it.
This syntax comes from C, where it's obligatory.
In C++ there is only one needed usage of this syntax
n3376 9.1/2
A class declaration introduces the class name into the scope where it is declared and hides any class, variable,
function, or other declaration of that name in an enclosing scope (3.3). If a class name is declared in a scope
where a variable, function, or enumerator of the same name is also declared, then when both declarations
are in scope, the class can be referred to only using an elaborated-type-specifier
struct stat {
// ...
};
stat gstat; // use plain stat to
// define variable
int stat(struct stat*); // redeclare stat as function
void f() {
struct stat* ps; // struct prefix needed
// to name struct stat
stat(ps); // call stat()
}
Code such as this comes directly from C (most likely via copy & paste), where the struct keyword is required before the name of any type that is defined as a struct (unless you add the appropriate typedef statement). Using struct in this way is still supported in C++ for backwards compatibility, but because struct foo { ... }; in C++ automatically adds foo as a type name, it is (usually) safe to refer to the type afterwards as just foo.
You are largely correct; in C++ the struct keyword is hardly ever relevant in declaring a variable.
More than you ever wanted to know about this: using struct keyword in variable declaration in C++
Below code works fine:
template<typename T> class X {};
class A; // line-1
void foo(); // line-2
int main ()
{
X<A> vA;
}
class A {};
void foo() {}
Let line-1 and line-2 are moved inside main(). The function doesn't get affected but the class A forward declaration doesn't work and gives compiler error:
error: template argument for template<class T> class X uses local
type main()::A
What you can observe is happening because, in C++, you can define classes inside functions.
So, if you place class A; in main, you are forward-declaring a class in scope of this function (i.e. class main::A), not in global scope (class A).
Thus, you are finally declaring an object of type X with a template argument of undefined class (X<main::A>).
error: template argument for template class X uses local type main()::A
This is the real problem - using a local type. In C++03 you cannot use local types as template arguments, because nobody had figured out how to name the resulting types.
What if you have several class A in several overloaded functions (again using the same name) - would the resulting X<A>'s then be the same type, or different types? How would you tell them apart?
In C++03 the standard passed on this, and just said "Don't do that!".
The problem was resolved in C++11 by deciding that X<A> using a local type A would be the same as if A had been declared in an anonymous namespace outside of the function, like
namespace
{
class A
{ };
}
int main()
{
X<A> vA;
}
So, with a newer compiler (or using a -std=cpp11 option), you can use a local class, and we also know what it means.
However, forward declaring a type inside a function still doesn't mean the same as forward declaring it in another scope. They will just be different types.
I've a class and an enum value which have the same name. Inside the class I want to use the enum which gives an error. Is there any way to use the enum without renaming or moving to a different namespace?
Example:
namespace foo {
enum bar {
BAD
};
class BAD {
void worse () {
bar b = BAD; // error
}
};
};
This is one of those tricky parts of how the name lookup is performed.
There are two identifier scopes in C++, one for class types and general identifier scope. The enum value BAD resides in the general identifier scope, while the class type BAR resides in the class identifier scope. That is the reason why you are allowed to have both an enum value and a class with the same name: both names do not collide.
Within class BAD, the identifier lookup rules will find the class BAD before it finds the enum, and thus the error. Now, if you fully qualify the identifier then the name lookup will first check the global identifier scope and match the enum value. On the opposite end, you will have to add the struct or class keyword to declare variables of type BAD.
namespace foo {
enum bad { BAD; };
class BAD {
void worse() { bad b = ::foo::BAD; } // fully qualified will match the enum
};
}
int main() {
// foo::BAD b; // error, foo::BAD is an enum, not a type
class foo::BAD b; // correct
}
Now, I would advice against this usage. It is generally not a good idea to reuse an identifier like this. Code will be more complex, and probably misleading for the casual reader (the same unqualified identifier refers to different things when used in different contexts). If the names do need to be BAD, consider using an enclosing namespace or class for either the class or the enum (prefer the enum there).
bar b = foo::BAD;
or if you are in the global namespace
bar b = ::BAD;
but that name overloading is not something I'd recommend. C++0X will allow
bar b = bar::BAD;
which is a better solution if the dependency on C++0X is acceptable.
As promised, the explanation
9.1/2
If a class name is declared in a scope where an object, function, or enumerator of the same name is also declared, then both declarations are in scope, the class can be referred to only using an elaborated-type-specifier (3.4.4)
The elaborated-type-specifier is the form
class BAD b;
This is for compatibility with C where tag names are in a different name space and must be [i]typedef[/i]ed if one want to use them without an elaborated-type-specifier. (A well known example with a function is the struct stat and the function stat in Unix).
That explain why the overloading of a name to designate a class and an enumerator is possible. The reason for which BAD designate the class here is that the name of the class is also defined into the class scope and in a member function definition the scope searched are in order:
- the member function scope
- the class scope
- the namespace containing the class definition
BAD is found at class scope, so the namespace foo is never searched.
No, there is no way to do that. You should use valid identifier. Valid identifier means that you have to be able to identify with it. :)
This works in VS2008, but gives a warning:
bar b = bar::BAD;
Its not something I can recommend.
You should put the enum within another namespace inside foo and qualify both bar and BAD with the new namespace.