0

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.

2
  • If you provide a default argument for the second template parameter of TList, you wouldn't need to manually insert a TNull. E.g. template<typename T, typename U = TNull> struct TList; TList<int,TList<int>> my_list; Commented Jan 14, 2014 at 18:50
  • Nice addition ! Thank you for your post ! Commented Jan 14, 2014 at 21:59

1 Answer 1

2

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.