Robert Dijkstra
Robert Dijkstra

Reputation: 73

C++ combining arguments template metaprogramming

I am new to templates and metaprogramming in C++. What I am trying to do now is the following: I have a struct with a template that expects non-type variadic pack of type char, defined trivially as follows:

template <char ... chs> 
struct MyStruct
{};

I have a second struct template which expects two types, like this:

template <typename ch1, typename ch2>
struct Together
{

};

What I'm trying to achieve is:

cout << Together<MyStruct<'a','b'>, MyStruct<'c','d'>>::result << '\n';

Which has to print: abcd

Thanks in advance

Upvotes: 5

Views: 794

Answers (3)

Constructor
Constructor

Reputation: 7493

Here is a a small improvement of the @Ryan Haining's answer:

template <char... Chars>
struct MyStruct
{
    static constexpr char value[] {Chars..., '\0'};
};

template <char... Chars>
constexpr char MyStruct<Chars...>::value[];

template <typename, typename>
struct Together;

template <char... Chars1, char... Chars2>
struct Together<MyStruct<Chars1...>, MyStruct<Chars2...>>
{
    using type = MyStruct<Chars1..., Chars2...>;
};

Live demo

Upvotes: 0

tux3
tux3

Reputation: 7330

This is a possible solution that closely matches the question using a std::string result :

template <char ... chs>
struct MyStruct
{
    static string stringify()
    {
        return stringify(chs...);
    }

    template <typename ... cst>
    static string stringify()
    {
        return string();
    }

    template <typename T, typename ... cst>
    static string stringify(T c, cst... cs)
    {
        return string() + c + stringify<cst...>(cs...);
    }
};

template <typename ch1, typename ch2>
struct Together
{
    static string result() {return ch1::stringify() + ch2::stringify();}
};

int main() {
    cout << Together<MyStruct<'a','b'>, MyStruct<'c','d'>>::result() << '\n';
    return 0;
}

It will of course work with more or less template parameters, like this :

Together<MyStruct<'a','b','c','d'>, MyStruct<'e','f','g'>>::result()

Upvotes: 1

Pradhan
Pradhan

Reputation: 16777

With templates, you can achieve pattern-matching through partial specialization. Declare a primary template declaration like this:

template <typename First, typename Second>
struct Together;

and then define a partial specialization for types with "look" a certain way:

template <char... ch1s, char... ch2s>
struct Together<MyStruct<ch1s...>, MyStruct<ch2s...>>
{
  std::string result;
  Together() : result({ch1s..., ch2s...}){}
};

Upvotes: 3

Related Questions