From here: Difference between 'struct' and 'typedef struct' in C++?, I found I need class identifier if there is name collision (for example if class name is the same as function name):
#include <iostream>
using namespace std;
class foo
{
public:
foo() {}
operator char const *() const
{
return "class";
}
};
char const *foo()
{
return "function\n";
}
int main()
{
char const *p;
p = class foo(); //this gets error
cout << p << '\n';
return 0;
}
output:
error: expected primary-expression before ‘class’
p = class foo();
What is primary expression here and how can I identify the class instead of the function? I would like it to print class instead of function. How to do so?
One of the possible solutions:
using bar = class foo;
p = bar();
int main()
{
char const *p;
struct foo f;
p = static_cast<char const*>(f);
cout << p << '\n';
return 0;
}
By the way, the answer you link mentions that one can use typedef class foo foo; to trigger a compiler error for a function of same name. Havning a class and a function of same name isn't something desirable, but rather you need to workaround a bit the fact that the language allows it. And don't miss the last paragraph:
I can't imagine why anyone would ever want to hide a class name with a
function or object name in the same scope as the class. The hiding
rules in C were a mistake, and they should not have been extended to
classes in C++. Indeed, you can correct the mistake, but it requires
extra programming discipline and effort that should not be necessary.
If you are in control of either the function or the class you should definitely rename it or place it inside a namespace.
I found two solutions that are accepted by both g++ and clang. I do not know, however, if they are standard C++.
Uniform initialization
cout << (class foo){} << "\n";
Using a helper
template <typename T, typename ...Args>
T ctor(Args&& ...args) {
return T{ std::forward<Args>(args) ... };
}
// ...
cout << ctor<class foo>() << "\n";
Related
I have a class with two constructors, one that takes no arguments and one that takes one argument.
Creating objects using the constructor that takes one argument works as expected. However, if I create objects using the constructor that takes no arguments, I get an error.
For instance, if I compile this code (using g++ 4.0.1)...
class Foo
{
public:
Foo() {};
Foo(int a) {};
void bar() {};
};
int main()
{
// this works...
Foo foo1(1);
foo1.bar();
// this does not...
Foo foo2();
foo2.bar();
return 0;
}
... I get the following error:
nonclass.cpp: In function ‘int main(int, const char**)’:
nonclass.cpp:17: error: request for member ‘bar’ in ‘foo2’, which is of non-class type ‘Foo ()()’
Why is this, and how do I make it work?
Foo foo2();
change to
Foo foo2;
You get the error because compiler thinks of
Foo foo2()
as of function declaration with name 'foo2' and the return type 'Foo'.
But in that case If we change to Foo foo2 , the compiler might show the error " call of overloaded ‘Foo()’ is ambiguous".
Just for the record..
It is actually not a solution to your code, but I had the same error message when incorrectly accessing the method of a class instance pointed to by myPointerToClass, e.g.
MyClass* myPointerToClass = new MyClass();
myPointerToClass.aMethodOfThatClass();
where
myPointerToClass->aMethodOfThatClass();
would obviously be correct.
Parenthesis is not required to instantiate a class object when you don't intend to use a parameterised constructor.
Just use Foo foo2;
It will work.
Adding to the knowledge base, I got the same error for
if(class_iter->num == *int_iter)
Even though the IDE gave me the correct members for class_iter. Obviously, the problem is that "anything"::iterator doesn't have a member called num so I need to dereference it. Which doesn't work like this:
if(*class_iter->num == *int_iter)
...apparently. I eventually solved it with this:
if((*class_iter)->num == *int_iter)
I hope this helps someone who runs across this question the way I did.
I was having a similar error, it seems that the compiler misunderstand the call to the constructor without arguments. I made it work by removing the parenthesis from the variable declaration, in your code something like this:
class Foo
{
public:
Foo() {};
Foo(int a) {};
void bar() {};
};
int main()
{
// this works...
Foo foo1(1);
foo1.bar();
// this does not...
Foo foo2; // Without "()"
foo2.bar();
return 0;
}
I ran into a case where I got that error message and had
Foo foo(Bar());
and was basically trying to pass in a temporary Bar object to the Foo constructor. Turns out the compiler was translating this to
Foo foo(Bar(*)());
that is, a function declaration whose name is foo that returns a Foo that takes in an argument -- a function pointer returning a Bar with 0 arguments. When passing in temporaries like this, better to use Bar{} instead of Bar() to eliminate ambiguity.
If you want to declare a new substance with no parameter (knowing that the object have default parameters) don't write
type substance1();
but
type substance;
Certainly a corner case for this error, but I received it in a different situation, when attempting to overload the assignment operator=. It was a bit cryptic IMO (from g++ 8.1.1).
#include <cstdint>
enum DataType
{
DT_INT32,
DT_FLOAT
};
struct PrimitiveData
{
union MyData
{
int32_t i;
float f;
} data;
enum DataType dt;
template<typename T>
void operator=(T data)
{
switch(dt)
{
case DT_INT32:
{
data.i = data;
break;
}
case DT_FLOAT:
{
data.f = data;
break;
}
default:
{
break;
}
}
}
};
int main()
{
struct PrimitiveData pd;
pd.dt = DT_FLOAT;
pd = 3.4f;
return 0;
}
I received 2 "identical" errors
error: request for member ‘i’ [and 'f'] in ‘data’, which is of non-class type ‘float’
(The equivalent error for clang is:
error: member reference base type 'float' is not a structure or union)
for the lines data.i = data; and data.f = data;. Turns out the compiler was confusing local variable name 'data' and my member variable data. When I changed this to void operator=(T newData) and data.i = newData;, data.f = newData;, the error went away.
#MykolaGolubyev has already given wonderful explanation. I was looking for a solution to do somthing like this MyClass obj ( MyAnotherClass() ) but the compiler was interpreting it as a function declaration.
C++11 has braced-init-list. Using this we can do something like this
Temp t{String()};
However, this:
Temp t(String());
throws compilation error as it considers t as of type Temp(String (*)()).
#include <iostream>
class String {
public:
String(const char* str): ptr(str)
{
std::cout << "Constructor: " << str << std::endl;
}
String(void): ptr(nullptr)
{
std::cout << "Constructor" << std::endl;
}
virtual ~String(void)
{
std::cout << "Destructor" << std::endl;
}
private:
const char *ptr;
};
class Temp {
public:
Temp(String in): str(in)
{
std::cout << "Temp Constructor" << std::endl;
}
Temp(): str(String("hello"))
{
std::cout << "Temp Constructor: 2" << std::endl;
}
virtual ~Temp(void)
{
std::cout << "Temp Destructor" << std::endl;
}
virtual String get_str()
{
return str;
}
private:
String str;
};
int main(void)
{
Temp t{String()}; // Compiles Success!
// Temp t(String()); // Doesn't compile. Considers "t" as of type: Temp(String (*)())
t.get_str(); // dummy statement just to check if we are able to access the member
return 0;
}
This code works:
struct Defs
{
static const int a = 1;
int b{};
void g() {}
};
struct Bob : Defs
{
void f()
{
cout << a << "\n";
cout << b << "\n";
g();
}
};
int main()
{
Bob b;
b.f();
}
But this code doesn't:
struct Defs
{
static const int a = 1;
int b{};
void g() {}
};
template<class D>
struct Bob : D
{
void f()
{
cout << a << "\n";
cout << b << "\n";
g();
}
};
int main()
{
Bob<Defs> b;
b.f();
}
Errors:
prog.cpp: In member function 'void Bob<D>::f()':
prog.cpp:16:11: error: 'a' was not declared in this scope
cout << a << "\n";
^
prog.cpp:17:11: error: 'b' was not declared in this scope
cout << b << "\n";
^
prog.cpp:18:5: error: there are no arguments to 'g' that depend on a template parameter, so a declaration of 'g' must be available [-fpermissive]
g();
^
prog.cpp:18:5: note: (if you use '-fpermissive', G++ will accept your code, but allowing the use of an undeclared name is deprecated)
But if I do the following, it works:
template<class D>
struct Bob : D
{
void f()
{
cout << D::a << "\n";
cout << D::b << "\n";
D::g();
}
};
Is it possible to get a class to use the members of a base class provided as a template parameter, without qualifying them? The reason I ask is because doing so would allow me to refactor some code without a LOT of changes.
It can be assumed the type used as the template parameter has all those members, otherwise a compile failure is acceptable.
Introduction
You get the error because the base-class is dependent on a template-parameter, which isn't too surprising since the base-class is the direct use of the template-parameter.
The error diagnostic comes from the fact that different template-parameters could yield significantly different behavior inside the class; what if the passed in template-parameter doesn't have a certain member; are we then to look up something in the global scope?
Where and why do I have to put the “template” and “typename” keywords?
Explicitly state that you would like to access a member of this
You are saying that you would like to access members of the base-class without qualifying them, and if I were to take you literally on this I would say that you could use this->member-name — but I doubt that this is what you are after given what you wrote about refactoring.
struct A {
int m;
};
template<class T>
struct B : T {
void func () {
this->m = 1;
}
};
int main () {
B<A> {}.func ();
}
Bring in names from the dependent base-class
Another alternative is to explicitly state that you would like certain names from your base-class to be available directly in that which derives from it— using using, as in the below:
template<class T>
struct B : T {
using T::m;
void func () {
m = 1;
}
};
The above can be read as; "dear compiler, wherever I'm referring to m I would like you to use the one in T".
But I want to hack the shit out of this problem; how!?
Alright, introduce a non-dependent base and have that introduce references to the data that you really want. This will work if you know what names that you will want to pull in for every T.
You can even extend this hack to automatically have it deduce the type of those members, but that is far away from the scope of the question.
#include <iostream>
struct A {
int n;
int m;
void print () {
std::cout << m << std::endl;
}
};
struct Hack {
template<class T>
Hack (T* hck) : m (hck->m), n (hck->n) { }
int& m;
int& n;
};
template<class T>
struct B : T, Hack {
B () : Hack (static_cast<T*> (this)) { }
void func () {
m = 123;
}
};
int main () {
B<A> b;
b.func ();
b.print ();
}
You can find a running example here. Word of warning; I would personally never do this, but as you can see it is possible to do what you ask through a little bit of indirection.
You can add:
using D::a;
using D::b;
using D::g;
to Bob to fix your scoping issue.
Here is a comprehensive overview of this problem. Honestly, it's a corner of C++ that shouldn't exist, but, no language is perfect =P
I have a class with two constructors, one that takes no arguments and one that takes one argument.
Creating objects using the constructor that takes one argument works as expected. However, if I create objects using the constructor that takes no arguments, I get an error.
For instance, if I compile this code (using g++ 4.0.1)...
class Foo
{
public:
Foo() {};
Foo(int a) {};
void bar() {};
};
int main()
{
// this works...
Foo foo1(1);
foo1.bar();
// this does not...
Foo foo2();
foo2.bar();
return 0;
}
... I get the following error:
nonclass.cpp: In function ‘int main(int, const char**)’:
nonclass.cpp:17: error: request for member ‘bar’ in ‘foo2’, which is of non-class type ‘Foo ()()’
Why is this, and how do I make it work?
Foo foo2();
change to
Foo foo2;
You get the error because compiler thinks of
Foo foo2()
as of function declaration with name 'foo2' and the return type 'Foo'.
But in that case If we change to Foo foo2 , the compiler might show the error " call of overloaded ‘Foo()’ is ambiguous".
Just for the record..
It is actually not a solution to your code, but I had the same error message when incorrectly accessing the method of a class instance pointed to by myPointerToClass, e.g.
MyClass* myPointerToClass = new MyClass();
myPointerToClass.aMethodOfThatClass();
where
myPointerToClass->aMethodOfThatClass();
would obviously be correct.
Parenthesis is not required to instantiate a class object when you don't intend to use a parameterised constructor.
Just use Foo foo2;
It will work.
Adding to the knowledge base, I got the same error for
if(class_iter->num == *int_iter)
Even though the IDE gave me the correct members for class_iter. Obviously, the problem is that "anything"::iterator doesn't have a member called num so I need to dereference it. Which doesn't work like this:
if(*class_iter->num == *int_iter)
...apparently. I eventually solved it with this:
if((*class_iter)->num == *int_iter)
I hope this helps someone who runs across this question the way I did.
I was having a similar error, it seems that the compiler misunderstand the call to the constructor without arguments. I made it work by removing the parenthesis from the variable declaration, in your code something like this:
class Foo
{
public:
Foo() {};
Foo(int a) {};
void bar() {};
};
int main()
{
// this works...
Foo foo1(1);
foo1.bar();
// this does not...
Foo foo2; // Without "()"
foo2.bar();
return 0;
}
I ran into a case where I got that error message and had
Foo foo(Bar());
and was basically trying to pass in a temporary Bar object to the Foo constructor. Turns out the compiler was translating this to
Foo foo(Bar(*)());
that is, a function declaration whose name is foo that returns a Foo that takes in an argument -- a function pointer returning a Bar with 0 arguments. When passing in temporaries like this, better to use Bar{} instead of Bar() to eliminate ambiguity.
If you want to declare a new substance with no parameter (knowing that the object have default parameters) don't write
type substance1();
but
type substance;
Certainly a corner case for this error, but I received it in a different situation, when attempting to overload the assignment operator=. It was a bit cryptic IMO (from g++ 8.1.1).
#include <cstdint>
enum DataType
{
DT_INT32,
DT_FLOAT
};
struct PrimitiveData
{
union MyData
{
int32_t i;
float f;
} data;
enum DataType dt;
template<typename T>
void operator=(T data)
{
switch(dt)
{
case DT_INT32:
{
data.i = data;
break;
}
case DT_FLOAT:
{
data.f = data;
break;
}
default:
{
break;
}
}
}
};
int main()
{
struct PrimitiveData pd;
pd.dt = DT_FLOAT;
pd = 3.4f;
return 0;
}
I received 2 "identical" errors
error: request for member ‘i’ [and 'f'] in ‘data’, which is of non-class type ‘float’
(The equivalent error for clang is:
error: member reference base type 'float' is not a structure or union)
for the lines data.i = data; and data.f = data;. Turns out the compiler was confusing local variable name 'data' and my member variable data. When I changed this to void operator=(T newData) and data.i = newData;, data.f = newData;, the error went away.
#MykolaGolubyev has already given wonderful explanation. I was looking for a solution to do somthing like this MyClass obj ( MyAnotherClass() ) but the compiler was interpreting it as a function declaration.
C++11 has braced-init-list. Using this we can do something like this
Temp t{String()};
However, this:
Temp t(String());
throws compilation error as it considers t as of type Temp(String (*)()).
#include <iostream>
class String {
public:
String(const char* str): ptr(str)
{
std::cout << "Constructor: " << str << std::endl;
}
String(void): ptr(nullptr)
{
std::cout << "Constructor" << std::endl;
}
virtual ~String(void)
{
std::cout << "Destructor" << std::endl;
}
private:
const char *ptr;
};
class Temp {
public:
Temp(String in): str(in)
{
std::cout << "Temp Constructor" << std::endl;
}
Temp(): str(String("hello"))
{
std::cout << "Temp Constructor: 2" << std::endl;
}
virtual ~Temp(void)
{
std::cout << "Temp Destructor" << std::endl;
}
virtual String get_str()
{
return str;
}
private:
String str;
};
int main(void)
{
Temp t{String()}; // Compiles Success!
// Temp t(String()); // Doesn't compile. Considers "t" as of type: Temp(String (*)())
t.get_str(); // dummy statement just to check if we are able to access the member
return 0;
}
Consider the following class structure:-
class foo {
public:
int fun () {
cout << "in foo" << endl;
}
};
class bar_class1:public foo {
public:
int fun () {
cout << "in bar_class1" << endl;
}
};
class bar_class2:public foo {
public:
float fun () {
cout << "in bar_class2" << endl;
}
};
main () {
foo * foo_pointer = new bar_class1();
foo_pointer->fun();
}
The output of the above program is in foo. Is there a way, that using a pointer of type foo * which actually points to an object of type bar_class1 or bar_class2, we can call the fun function of the derived class instead of the base class? I am not able to make the fun function virtual in the base class foo since, then there is a return type conflict for function foo in the derived class bar_class2.
Here's my comments as an answer.
You cannot do that.
If that kind of polymorphism were possible, wouldn't that break horribly when code calls foo::fun (expecting an int) on an object whose actual type is bar_class2 and thus gets a float? Do you want to simply throw away type safety?
If you want different return types, sounds like you want a template. But you cannot use templates quite in the way that you want to use foo(). Static polymorphism (templates) and run time polymorphism (late binding) don't mix well. You need to redesign your oop structure.
If you absolutely hate type safety, you can sort of do this with void pointers. But for the love of Flying Spaghetti Monster, don't ever do this in c++. Please close your eyes before reading the following code to avoid exposure.
#include <iostream>
class foo {
public:
virtual void* fun() = 0;
virtual ~foo(){};
};
class bar_class1: public foo {
public:
void* fun() {
return &value;
}
private:
int value = 1;
};
class bar_class2: public foo {
public:
void* fun() {
return &value;
}
private:
float value = 1.1;
};
int main() {
foo* foo_pointer1 = new bar_class1();
foo* foo_pointer2 = new bar_class2();
// in c++ compiler must know the type of all objects during compilation
std::cout << *reinterpret_cast<int*>(foo_pointer1->fun()) << '\n';
std::cout << *reinterpret_cast<float*>(foo_pointer2->fun()) << '\n';
delete foo_pointer1;
delete foo_pointer2;
}
Perhaps similar to the existing answer, I really hope you realize changing your design is better than this mess, but I believe it's the best you're going to get. I force you to specify the return type at the callsite (e.g., someFoo->fun<int>()), since you're going to have to know it anyway, and dispatch based on that. Any funny business and you'll get an exception. Also keep in mind the performance of this is, I imagine, less than desirable.
#include <cassert>
#include <stdexcept>
#include <type_traits>
struct foo {
virtual ~foo() = default;
template<typename T, typename = typename std::enable_if<std::is_same<T, int>::value>::type, typename = void>
T fun();
template<typename T, typename = typename std::enable_if<std::is_same<T, float>::value>::type>
T fun();
};
struct bar_class1 : foo {
int fun() {
return 2;
}
};
struct bar_class2 : foo {
float fun() {
return 3.5f;
}
};
template<typename T, typename, typename Dummy>
T foo::fun() {
if (auto *p = dynamic_cast<bar_class1 *>(this)) {
return p->fun();
} else if (dynamic_cast<bar_class2 *>(this)) {
throw std::invalid_argument("Mismatching dynamic type.");
} else {
return 1;
}
}
template<typename T, typename>
T foo::fun() {
auto *p = dynamic_cast<bar_class2 *>(this);
if (dynamic_cast<bar_class1 *>(this) || !p) {
throw std::invalid_argument("Mismatching dynamic type.");
} else if (auto *p = dynamic_cast<bar_class2 *>(this)) {
return p->fun();
}
assert(false); //should never get here, but compiler doesn't know that
}
If you'd like the main function, I've written a complete sample.
To answer your question: No, late binding isn't possible without deciding the return type. ...at least not in a reasonable manner, see user2079303's great counter-example. But...
you may change your code (for example) into something like the following, using the keyword virtual and equalize the return type for instance to void:
class foo
{
public:
virtual void fun(std::ostream& out) {
out << "in foo" << std::endl;
}
};
so you can decide the output type later:
class intFoo: public foo
{
public:
void fun(std::ostream& out) {
// output an int
out << "in bar_class1. data: " << data << endl;
}
int data;
};
class floatFoo: public foo
{
public:
void fun(std::ostream& out) {
// output a float
out << "in bar_class2. data: " << data << endl;
}
float data;
};
For brevity, I double-use the output stream - now a parameter of the function fun() - function to demonstrate type-dependent portion of your derived class. In your application, the parameter will probably be of another, more useful type.
The function fun is not a virtual function since you didn't use the keyword "virtual" to decorate it. So, the compile will determine which function to call at compiling time. So, there is no way to tell the compiler to call another function because the compiler will use its static type, i.e. the variable definition type -- foo *.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Where and why do I have to put the “template” and “typename” keywords?
recently a piece of code confused me:
class A {
public:
typedef int SomeType;
void func(SomeType i);
SomeType func2();
};
void A::func(SomeType i) {
cout << "in A, value: " << i << endl;
}
SomeType A::func2() {
return 123;
}
int main() {
A a;
}
G++ 4.4 gives a compile error that it does not know the SomeType while compiling A::func2:
error: 'SomeType' does not name a type
But the same SomeType compiles well in A::func(SomeType i):
class A {
public:
typedef int SomeType;
void func(SomeType i);
};
void A::func(SomeType i) {
cout << "in A, value: " << i << endl;
}
Anyone can help me to understand this? It seems C++ treats unfair to argument types and return types?
gcc is right -
/* can't use unqualified name */ A:: /* can use unqualified name */ () {
}
Before the A::, you need to qualify the nested type with A::. So you need:
A::SomeType A::func2() {
//whatever
}
You need to change
SomeType A::func2() {
to
A::SomeType A::func2() {
The reason that this differs from func1() is that SomeType is used in the parameter list there so that the compiler knows that it can look in class A for the type. However, with func2(), SomeType is the return type and the compiler doesn't know to look in class A yet.
Simply change the definition of func2 to:
A::SomeType A::func2() {
return 123;
}
You need to tell the compiler you want to use the SomeType typename defined inside class A.
Instead, use this Qualify SomeType with the class name as in
A::SomeType A::func2() {
(...)
}
SomeType cannot be used outside the A class and func2 is visible outside the A class
This URL - states the following in the C++ specification
http://balbir.blogspot.com/2005/06/scope-of-typedefs-in-class-in-c.html
In particular, type names defined within a class definition cannot be used
outside their class without qualification.