Conflicting declaration in c++ - c++

I have a cpp file as follows:
#include <iostream>
#include "i.h"
using namespace std;
typedef struct abc{
int a1;
int b1;
} abc_t, *abc;
void fun(abc x){
cout<<x->a1;
}
int main(){
abc val;
fun(val);
return 0;
}
The i.h file :
struct abc;
void fff(struct abc);
When I am compiling the code following error occurs:
t.cpp:8: error: conflicting declaration ‘typedef struct abc* abc’
t.cpp:5: error: ‘struct abc’ has a previous declaration as ‘struct abc’
t.cpp: In function ‘void fun(abc)’:
t.cpp:11: error: base operand of ‘->’ has non-pointer type ‘abc’
If I save the cpp file as c file and compile using c compiler then everything works fine.
What is the issue with c++ compiler?

You've declared abc as both a struct and a pointer to a struct by using typedef. It's the same as doing:
struct abc {...};
typedef abc abc_t; // ok, abc_t is now an alias for abc
typedef abc *abc; // error
Skip the typedef, abc_t and *abc and use the class (with all members public per default) abc as-is.
i.h
struct abc {
int a1 = 0;
int b1 = 0;
};
void fun(const abc& x);
i.cpp
#include <iostream>
#include "i.h"
void fun(const abc& x) {
std::cout << x.a1 << "\n";
}
main.cpp
#include <iostream>
#include "i.h"
int main(){
abc val;
fun(val);
return 0;
}

In C, this:
struct abc
{
int a1;
int b1;
};
creates a type struct abc (roughly speaking), but not a type abc.
That's why you use the typedef trick to create a type we can use without having to write struct everywhere:
typedef struct abc{
int a1;
int b1;
} abc_t;
Now you have the type abc_t, too, which is the same as struct abc. There is still no type abc.
So when you add on the declaration of a pointer called abc, that's valid, as the name is not taken yet.
In C++, the original declaration creates a type named abc. There is no need for the typedef trick, and your declaration of a pointer called abc is invalid because the name abc is taken.
Solution
You can disambiguate your names (and de-obfuscate the code) like so:
struct abc
{
int a1;
int b1;
};
typedef struct abc abc_t;
abc_t* ptr_to_abc;
Or, if you are writing C++ and don't need C compat, just this:
struct abc
{
int a1;
int b1;
};
abc* ptr_to_abc;

This
struct abc;
in C++ declares the type struct abc as well as the type abc, which then clashes with typedef'ing ...*abc again.
In C it just declares struct abc, so typedef'ing ...*abc does not produce a duplicate declaration.

Related

Access type through another type in the same namespace

I have two structs A and B that live in the same namespace. For architectural and compatibility reasons I want to have A accessible through B.
I tried the following which is not working:
#include <iostream>
struct A
{
static void print()
{
std::cout << "hello SO!" << std::endl;
}
};
struct B
{
typedef A A; // error here
};
int main()
{
B::A::print();
return 0;
}
Apparently the typedef to the same name is not working. With g++ I get the following error:
foo.cpp:13:15: error: declaration of ‘typedef struct A B::A’ [-fpermissive]
typedef A A;
^
foo.cpp:3:8: error: changes meaning of ‘A’ from ‘struct A’ [-fpermissive]
struct A
It would work if I give it an other name (e.g. typedef A A2) but I want it to keep the same name.
Interestingly, it is actually working when I compile with clang but I would need code that also builds with gcc.
Is there some way to achieve this (i.e. being able to do B::A::print())?
I am currently using C++11 but going to a newer version might be possible if it is necessary.
just use typedef ::A A or using A = ::A
https://godbolt.org/z/VVKk3V
Here is a solution:
#include <iostream>
namespace NS {
struct A {
static void print() { std::cout << "hello SO!" << std::endl; }
};
struct B {
using A = NS::A;
};
} // namespace NS
int main() {
NS::B::A::print();
return 0;
}
Compiles fine.

About pointer to member function of derived class

Here's my code, and the IDE is DEV C++11
#include<iostream>
using namespace std;
class A{
public:
int a=15;
};
class B:public A
{
};
int main(){
int A::*ptr=&B::a; //OK
int B::*ptr1=&A::a; //why?
int B::A::*ptr2=&B::a;//why?
int B::A::*ptr3=&A::a; //why?
}
I have read Programming Languages — C++ and I know the type of &B::a is int A::*, but I don't realise why the next three lines will pass the compilation.
And the weirdest thing to me is the syntax of int B::A::* , what's the meaning of this? I'm just a newcomer of C/C++, so please tolerate my weird question.
Diagram representation may help you understand why it is ok and compiles
Interesting will be once you reinitialize the same variable in inherited class
#include<iostream>
using namespace std;
class A {
public:
int a = 15;
};
class B :public A
{
public:
int a = 10;
};
int main() {
int A::*ptr = &B::a; //Waring class B a value of type int B::* cannot be
//used to initialize an entity of type 'int A::*'
int B::*ptr1 = &A::a; // why?
int B::A::*ptr2 = &B::a;//Waring class B a value of type int B::* cannot
// be used to initialize an entity of type 'int A::*'
int B::A::*ptr3 = &A::a; //why?
}

A confusing typedef involves class scope

I'm reading code of a C++ project and it contains some code of the following form:
namespace ns {
class A {};
class B {};
}
struct C {
typedef ns::A* ns::B::* type;
};
Can someone explain the meaning of the typedef line? type seems to be some kind of pointer to member of ns::B which points to ns::A, but I'm not sure.
Class A and B in the real code are not empty, but I think it's not relevant here. And here is a live example.
ns::B::*
is a pointer-to-member-variable of B. Then ns::A* is its type.
So the whole declaration means
pointer-to-member-variable of B of type ns::A*
The answer by #vsoftco already answers the core of the question. This answer shows how one might use such a typedef.
#include <iostream>
#include <cstddef>
namespace ns {
struct A {};
struct B
{
A* a1;
A* a2;
};
}
struct C {
typedef ns::A* ns::B::*type;
};
int main()
{
C::type ptr1 = &ns::B::a1;
C::type ptr2 = &ns::B::a2;
ns::B b1;
b1.*ptr1 = new ns::A; // Samething as b1.a1 = new ns::A;
return 0;
}

How to have a c++ object with a method that takes argument the enclosing class?

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.

Namespace Scope Question

I have a quick question about namespace scope:
I have two namespaces, A and B, where B is nested inside A.
I declare some typedefs inside A.
I declare a class inside B ( which is inside A )
To access the typedefs (declared in A), from inside B, do I need to do "using namespace A;"
ie:
B.hpp:
using namespace A;
namespace A {
namespace B {
class MyClass {
typedeffed_int_from_A a;
};
}
}
This seems redundant... Is this correct?
To access the typedefs (declared in A), from inside B, do I need to do "using namespace A;"
No.
However if there is a typedef or some other symbol with same name as your typedef, defined in the namespace B, then you need to write this:
A::some_type a;
Lets do a simple experiment to understand this.
Consider this code: (must read the comments)
namespace A
{
typedef int some_type; //some_type is int
namespace B
{
typedef char* some_type; //here some_type is char*
struct X
{
some_type m; //what is the type of m? char* or int?
A::some_type n; //what is the type of n? char* or int?
};
void f(int) { cout << "f(int)" << endl; }
void f(char*) { cout << "f(char*)" << endl; }
}
}
int main() {
A::B::X x;
A::B::f(x.m);
A::B::f(x.n);
return 0;
}
Output:
f(char*)
f(int)
That proves that type of m is char* and type of n is int as expected or intended.
Online Demo : http://ideone.com/abXc8
No, you don't need a using directive; as B is nested inside of A, the contents of A are in scope when inside B.