Reputation: 309
I recently spent some time hunting down a typo in my C++ templates. g++ did not complain about the typo, so I was wondering if there is a tool which can check for this type of problem in the future?
Here is a simplified example which demonstrates the correct compilation. I would expect a complaint about struct dummy not being defined, but it seems like the templated class goo hides that.
foo.h:
struct smart {
int x, y, z;
};
template<typename T> class goo
{
void barf(T* ptr){}
};
template<typename T> class foo
{
public:
foo(){};
private:
goo<T> x;
};
class bar: public foo<struct dummy>
{
public:
void do_something(struct smart& thing){}
};
foo.cpp:
#include "foo.h"
int main()
{
bar a;
struct smart b;
a.do_something(b);
return b.x+b.y+b.z;
}
Compiles successfully with g++ foo.cpp
Upvotes: 1
Views: 265
Reputation: 21721
Attilla has nailed this; the definition of dummy
is not needed
and so it can remain as an incomplete type. This is an extremely useful
feature of C/C++ as it helps with information hiding and also with
reducing compile times.
For example:
// Afwd.h
class A;
A * getA ();
void processA(A *);
void printA (A *);
// t.cc
#include "Afwd.h"
void bar ()
{
A * a = getA ();
processA (a);
printA (a);
}
Here, it's unnecessary for clients of A
to see its implementation details. This also has the advantage that clients do not need to include headers that are required for the definition of A
In order to generate an error against dummy
in the original example, the definition must be used in this translation unit.
Firstly, ptr
needs to be used in a way which requires a complete type, for example via a dereference:
template<typename T> class goo
{
public:
void barf(T* ptr){
*ptr;
}
};
This still isn't a problem as the function barf
is not called and so is not instantiated:
template<typename T> class foo
{
public:
foo(){
x.barf (0);
};
private:
goo<T> x;
};
This code now generates an error. The constructor of bar
instantiates and calls the definition of foo
which instantiates and calls barf
.
Upvotes: 0
Reputation: 31559
It's because you use struct dummy
the compiler is told to auto generate a forward declaration struct if there is no such struct exiting. If you use just dummy
without struct
it will not do so and it will complain.
Upvotes: 2
Reputation: 101446
The compiler, set at the highest warning levels, is the best tool you have for detecting any C++ issue.
My advice to you is two fold:
1) Set your compiler warning levels at the highest level. This will catch many mistakes that lower levels may remain silent on.
2) Use a coding style that is more apt to generate compiler errors when you do something wrong. For example:
class bar: public foo<struct dummy>
{
public:
void do_something(struct smart& thing){}
};
I honestly don't know if this code is legal or not. I strongly suspect not, but it does appear that you're declaring a new type struct dummy
. The compiler accepts it, and so I'm not sure if it's legit.
You would have been well-served by doing this instead:
class bar: public foo<dummy>
{
public:
void do_something(struct smart& thing){}
};
Now this can never be parsed as a new type declaration, and the compiler will refuse it. This would have caught your problem early.
Upvotes: 3
Reputation: 28762
If you are not using the template type parameters (which is the case in your example) the code is OK, even if the type does not exist or you are calling a function on the type in a member function that is not being called. This is in the name of C++'s if you don't use it you don't pay for it (e.g no new function is created).
Upvotes: 2