问题
It is very difficult for me to explain this particular problem/question so please bear with me (I am having trouble with all my template related questions!).
Take this code as an example (note that the point of showing the code is to show a complex template hierarchy, not whether it makes sense):
#include <string>
#include <vector>
#include <list>
template <typename T>
struct Foo
{
typedef typename T::value_type value_type;
typedef typename T::value_type1 value_type1;
typedef typename T::value_type2 value_type2;
Foo() {}
Foo(value_type1, value_type, value_type2) {}
Foo(value_type, value_type1, value_type2) {}
};
template <typename T, typename T1, typename T2>
struct MiddleMan
{
typedef T value_type;
typedef T1 value_type1;
typedef T2 value_type2;
};
template <typename T>
struct MainClass
{
typedef typename T::value_type value_type;
typedef typename T::value_type1 value_type1;
typedef typename T::value_type2 value_type2;
typedef MainClass<T> this_type;
typedef Foo<this_type> iterator;
};
using namespace std;
int main()
{
typedef MiddleMan<string, vector<string>, list<vector<string> > > mm;
MainClass<mm>::iterator a(1, 2, 3);
return 0;
}
and assume this is the error you are getting
None of the 3 overloads could convert all the argument types
Note that I know in this instance, if you compile the code, the error message is not the same as above but the error message in my complex template code that I am currently working on is the above. I just presented a simplified example to help with the question.
Now I want to know the types of Foo
, i.e. value_type
, value_type1
, value_type2
so that I can fix the error, without tracing back all the way to MiddleMan. The reason I don't want to trace manually is that the code can be quite complex template code where a trace back is very difficult to do.
I figured since the compiler has already figured out the types, it should be able to let me know, i.e. there should be an easy way to figure it out at compile time (maybe through a message in the output window) the types attached to the typedef
s. Is there an easy way?
SOLUTION-EDIT: Here is another example that may help future SOer after reading the selected answer:
template <typename T> struct incomplete;
template <typename T, typename T2, typename T3>
class foo
{
public:
typedef T value_type;
typedef T2 value_type2;
typedef T3 value_type3;
};
int main()
{
// Assume the following type is much more complex
typedef foo<float, int, char> type_i_am_having_trouble_with;
// At this point you are instantiating it, and the program compiles (or maybe
// not) and you have no idea what some of the typedefs stand for
type_i_am_having_trouble_with b;
// Use this to find out what the typedefs stand for
incomplete<type_i_am_having_trouble_with::value_type> test;
}
Output from Visual C++ 2008:
error C2079: 'test' uses undefined struct 'incomplete<T>'
1> with
1> [
1> T=float
1> ]
回答1:
There are a few tricks to get the compiler to show you the actual type of a typedef. One is to try to instantiate an incomplete type.
template<typename>
struct Printer;
typedef std::vector<int> foobartype;
Printer<foobartype> printer;
There is also boost::mpl::print which can actually issue a warning instead of erroring out.
All those techniques have to be used at the place where the typename is actually accessible so you will have to 'trace' through the code eventually.
Sadly, debugging template code is pretty much a black art and often you will have to play compiler and instantiate things in your head to get to the issue.
来源:https://stackoverflow.com/questions/8958202/output-the-type-of-a-typedef-at-compile-time-in-c-specifically-when-an-error