This question is similar to, but more specific than, this other question:
using struct keyword in variable declaration in C++.
Consider the following program:
#include <stdio.h>
struct Foo {
int x;
int y;
};
Foo getFoo() {
Foo foo;
return foo;
}
int main(){
getFoo();
}
The above program compiles with g++ but not gcc.
We can modify the program as follows to make it compile with both gcc and g++:
#include <stdio.h>
struct Foo {
int x;
int y;
};
struct Foo getFoo() {
struct Foo foo;
return foo;
}
int main(){
getFoo();
}
Is this use of the struct keyword guaranteed by the standard to be well-defined in C++?
Yes. That's known as an elaborated-type-specifier.
Related
Consider the following code.
namespace A::B::C::D::E {
struct X { };
}
namespace B {
using namespace A::B::C::D::E;
// or, using A::B::C::D::E::X;
// or, using X = A::B::C::D::E::X;
}
Let's say I use B::X incorrectly in some way and get an error. That error, in clang at least, will look something like
error: ... for type A::B::C::D::E::X.
I'd much rather have the error stated for B::X.
Is there a way to configure clang error messages to use the locations of using declarations, instead of the aliased entity?
I think it is good that the compiler uses A::B::C::D::E::X because otherwise it could be ambiguous. Like in the following example:
namespace A::B::C::D::E {
struct X {
int y;
};
}
namespace B {
using namespace A::B::C::D::E;
void foo() {
X aa;
B::X bb;
aa.y = 0;
}
struct X {
int z;
};
void bar() {
X aa;
B::X bb;
aa.y = 0;
}
}
int main() {
return 0;
}
There can be a struct X declared in the B namespace, and then that is B::X and it is necessary to call the other one A::B::C::D::E::X since otherwise they could not be distinguished.
Consider such simple example:
namespace foo {
struct Foo {};
struct Boo {
void f(Foo);
};
}
using foo::Boo;
void Boo::f(Foo)
{
}
clang and gcc compile such code without errors (-pedantic -std=c++11),
but VC++-2015 report error about Foo type in void Boo::f(Foo) - Foo underclared identifier. If rewrite code like this: void Boo::f(foo::Foo) it compiles just fine, but what interesting it also compiles after such rewrite:
namespace foo {
struct Foo {};
struct Boo {
void f(Foo);
};
}
void foo::Boo::f(Foo)
{
}
is it VC++2015 bug according to c++11 standard?
No, this isn't an MSVC bug. You should properly namespace your identifiers.
is there any way to define an object in a way similar to the line below???
template<typename T>
struct A {
T *data;
//...
typedef T data_type;
};
int main() {
A<int>::data_type a; // ok
A<int> obj;
obj.data_type b; // <-- is it possible to do something like this??
}
Thanks!
Massimo
You can use decltype on expressions. The code for your case would be:
decltype(obj)::data_type b;
From C++11 onwards it is possible:
decltype(obj) is evaluated at compile-time and is the type of obj. It can be used whenever a type is used.
So you could write decltype(obj)::data_type b;
decltype is a keyword and is particularly useful in generic programming.
This seems to work fine; use decltype() for c++11; you can try typeof() pre c++11
typeof() in gcc: https://gcc.gnu.org/onlinedocs/gcc/Typeof.html
#include <iostream>
using namespace std;
template<typename T>
struct A {
T *data;
//...
typedef T data_type;
};
int main() {
A<int>::data_type a; // ok
A<int> obj;
decltype(obj)::data_type b; // <-- is it possible to do something like this??
}
After I read the reference link: Must provide destructor in the PIMPL, I do the follow the example, but the g++(4.6.1) doesn't generate compile error as I expected
The source code is:
// Predeclare.h
#include <vector>
#include <boost/scoped_ptr.hpp>
#include <iostream>
struct A;
class Predeclare
{
std::vector<A> alist_;
boost::scoped_ptr<A> pa_;
//A a;
public:
Predeclare();
//~Predeclare();
void print();
void set(int i);
};
// Predeclare.cpp
#include "Predeclare.h"
struct A
{
int a;
};
Predeclare::Predeclare(): pa_(new A)
{}
/*
Predeclare::~Predeclare()
{}
*/
void Predeclare::print()
{
std::cout << pa_->a << '\n';
}
void Predeclare::set(int i)
{
pa_->a = i;
}
int main()
{
Predeclare c1;
c1.set(10);
c1.print();
return 0;
}
Then, compile the program
g++ Predeclare.cpp
Everything is ok, Why the g++(4.6.1) doesn't generate compile error?
In your example, the compiler only needs a destructor for Predeclare when it reaches the declaration of c1 in main(). By that point, A has already been defined, earlier in Predeclare.cpp.
If you were to try to instantiate Predeclare in a different source file, you would likely run into problems.
Note that instantiating std::vector<A> where A is incomplete yields undefined behavior. When you instantiate a container, the value type must be Destructible, and only complete types are Destructible.
I am trying to figure out if there's any known pattern/idiom in c++ for what I am trying to do here. Class A must be composed of an object that has a function whose argument must also be of type A. The following code doesn't compile since typeid may not be used in a constant expression. Any suggestions?
#include <iostream>
#include <typeinfo>
using namespace std;
template <typename T>
struct B {
int f(T& i) { cout << "Hello\n"; }
};
class A {
B<typeid(A)> b;
};
int main()
{
A k;
}
Your stated requirements don't need templates at all, just a forward declaration:
#include <iostream>
class A; // forward declare A
struct B {
int f(A &i); // declaration only, definition needs the complete type of A
};
class A {
B b;
};
int B::f(A &i) { std::cout << "Hello\n"; } // define f()
int main()
{
A k;
}
You are looking for B<A> b; The following program compiles without error or warning on g++ 4.4.3.
#include <iostream>
#include <typeinfo>
using namespace std;
template <typename T>
struct B {
int f(T& i) { cout << "Hello\n"; return 0; }
};
class A {
public:
B<A> b;
};
int main()
{
A k;
return k.b.f(k);
}
Note: If you are using templates only to avoid forward declaration, my solution is wrong. But, I'll leave it here in case you are using templates for some other legitimate reason.