Why does the conversion operator need a definition of the class converted to?

phinz

Consider the following code:

// A.hpp
class B;
class A
{
public:
    B b();
    operator B(){return b();}
};


// B.hpp
class B{
};

// A.cpp
// would include B.hpp and A.hpp
B A::b(){
    return {};
}

// main.cpp
// would include A.hpp and B.hpp
int main()
{
    A a{};
    B b(a);
}

It does not compile:

files.cpp:7:17: error: return type ‘class B’ is incomplete
    7 |     operator B(){return b();}
      |                 ^
files.cpp: In member function ‘A::operator void()’:
files.cpp:7:26: error: invalid use of incomplete type ‘class B’
    7 |     operator B(){return b();}
      |                         ~^~
files.cpp:2:7: note: forward declaration of ‘class B’
    2 | class B;
      |       ^
files.cpp: In function ‘int main()’:
files.cpp:26:12: error: no matching function for call to ‘B::B(A)’
   26 |     B b(A{});
      |            ^
files.cpp:12:7: note: candidate: ‘constexpr B::B()’
   12 | class B{
      |       ^
files.cpp:12:7: note:   candidate expects 0 arguments, 1 provided
files.cpp:12:7: note: candidate: ‘constexpr B::B(const B&)’
files.cpp:12:7: note:   no known conversion for argument 1 from ‘A’ to ‘const B&’
files.cpp:12:7: note: candidate: ‘constexpr B::B(B&&)’
files.cpp:12:7: note:   no known conversion for argument 1 from ‘A’ to ‘B&&’

Why can't the conversion operator A::operator B() delegate to A::b() without B being defined?

Sam Varshavchik
 operator B(){return b();}

The compiler must compile b(). To do this, the compiler needs to know what the mysterious B class is all about. The simple reason for this is because the C++ standard requires this. There's always a single reason for why anything has to be in some particular way, in C++: it's required by the standard.

As far as practical reasons go, there can be many. For example, on some implementations objects that get returned from a function that are small enough may be returned in a specific CPU register. Bigger objects will require a different approach. The compiler must know what to do, in order to actually compile this return statement. That's actual code. That's not a declaration, that you can get away with, with a forward-declared type.

Your solution is very simple. Just declare the conversion operator:

 operator B();

Then, later in the code, after B is defined, and at the precise location where A::b gets defined, define A::operator B() in exactly the same way. Problem solved.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

Why does outputting a class with a conversion operator not work for std::string?

Why does an out-of-class member template definition need a repetition of its declaration 'requires-clause'

Objects of a class that does not have operator ==() are converted to another type

Why does c++ && operator need priority

Why does 'this' need to be dereferenced in this case? (assignment operator)

Why does C++ need operator synonyms?

Why does operator new need constructor to be public?

Why does the "as" operator not use an implicit conversion operator in C#?

Why does this class definition result in a NoMethodError?

Why does this not marking an operator overload as inline cause a duplicate definition error?

Why does gcc need the definition of unused _Generic values?

Why does an implicit conversion operator from <T> to <U> accept <T?>?

Why does static_cast not use the conversion operator to pointer to const?

Why does a unary operator enable a ()=>X implicit conversion?

Why does the creation of a map in scala not need and allow the new operator?

Why does overloading ostream's operator<< need a reference "&"?

Why does Map's + operator need double parentheses?

Why does an ostream iomanip not need template parameters when passed to operator<<?

Why does std::rel_ops need equality operator?

Why isn't a class converted automatically in DataGrid when implicit conversion exists?

Why does the class definition's metaclass keyword argument accept a callable?

Why does constexpr static member (of type class) require a definition?

Why does Random class have no minimal complete definition

Why does a class' body get executed at definition time?

Why does a class definition always produce the same bytecode?

Why the Class definition does compile one way and not the other?

Why such operator definition is possible in Scala?

why does class cast does not take effect in java ternay operator

Why the need for browserify `paths` definition?

TOP Ranking

HotTag

Archive