Reputation: 178
I want to build a simple TList using template meta-programming and I have two questions for why it is not working. Here is the code:
struct TNull{};
template<typename T,typename U>
struct TList
{
typedef T THead;
typedef U TTail;
THead head;
TTail tail;
};
template<typename T>
void Foo(TList<T,TNull> &list)
{
std::cout<<list.head<<" ";
}
template<typename T,typename U>
void Foo(TList<T,U> &list)
{
std::cout<<list.head<<" ";
//Foo<int,TNull>(list.tail); // COMM_1
Foo<decltype(list.tail.head),decltype(list.tail.tail)>(list.tail); //COMM_2
}
int main (int argc, const char * argv[])
{
TList<int,TList<int,TNull>> list;
Foo(list);
return 0;
}
First, I would like to know how to write the COMM_2 line so the template will expand until it reaches the TNull then it stops. I tried different methods and none of it works
The second question is if I write the expansion by myself (like in COMM_1) I expect the compiler to pick the first Foo overload but it doesn't, it gives me an error. Why is this behavior? I was expecting the compiler to pick the best match for a specific set of arguments.
I am testing this feature using Visual c++ 2010, which has no support for variadic template arguments, and this is for a project at my workplace so switching compilers is not an option for me.
Upvotes: 0
Views: 946
Reputation: 8095
Simply call Foo(list.tail)
. The compiler will determine the function to call and deduce the template parameters based on the types of the function arguments. This code works in gcc under -std=c++98
, and prints "1 2 \n".
#include <iostream>
struct TNull{};
template<typename T,typename U>
struct TList {
typedef T THead;
typedef U TTail;
THead head;
TTail tail;
};
template<typename T>
void Foo(TList<T,TNull> &list)
{
std::cout << list.head << " ";
}
template<typename T,typename U>
void Foo(TList<T,U> &list)
{
std::cout << list.head << " ";
Foo(list.tail);
}
int main (int argc, const char * argv[])
{
TList<int,TList<int,TNull> > list;
list.head = 1;
list.tail.head = 2;
Foo(list);
std::cout << "\n";
return 0;
}
Note that this will not work with empty lists. For that, you should write your Foo
functions so that the base case is a TNull
, as opposed to a TList
with a TNull
tail.
Upvotes: 2