Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Change the meaning of code by replacement of forward declaration with include

Google C++ Style Guide states that

In extreme cases, replacing an #include with a forward declaration can silently change the meaning of code.

Can you please help me to find some examples?

like image 434
Peter Avatar asked May 04 '15 14:05

Peter


People also ask

Why use forward declaration instead of include?

A forward declaration is much faster to parse than a whole header file that itself may include even more header files. Also, if you change something in the header file for class B, everything including that header will have to be recompiled.

Should I use forward declaration or include?

As the name itself implies, forward declaration is just a Declaration and not a definition. So, you will declare saying the compiler that it is a class and I just declaring it here and will provide you the definition when am gonna use it. So, normally you forward declare in the Header file and #include in the .

Which kind of code can use a forward declaration to a class instead of including a header file with a full definition of the class?

You will usually want to use forward declaration in a classes header file when you want to use the other type (class) as a member of the class. You can not use the forward-declared classes methods in the header file because C++ does not know the definition of that class at that point yet.

What is the use of forward declaration in C++?

In C++, Forward declarations are usually used for Classes. In this, the class is pre-defined before its use so that it can be called and used by other classes that are defined before this. Example: // Forward Declaration class A class A; // Definition of class A class A{ // Body };


1 Answers

Here are two cases. One of them is UB, the other I think is defined change of behavior (assuming no ODR or similar violations: ie, no call to foo ever sees the definition of A, but I am uncertain)

namespace N {
  struct B {};
  struct A;//:B{};
}

void foo(N::B*){
  std::cout << "B\n";
}
template<class T, class=std::enable_if_t<!std::is_convertible<T*,N::B*>{}>>
void foo(T*){
  std::cout << "T\n";
}

int main() {
  foo( (N::A*)0 );
}

replacing struct A; with struct A:B{}; will change which of the foo overloads are called.

In addition, delete A; will call ~A() if its is visible when delete A; is called. Otherwise, if there is a non-trivial destructor, we have UB. In this case, the meaning of the code changes in that it goes from UB to DB, which is I suppose a change of meaning.

like image 193
Yakk - Adam Nevraumont Avatar answered Oct 07 '22 21:10

Yakk - Adam Nevraumont