Brandon
Brandon

Reputation: 23515

Type of unpacked argument

I have the following code:

template<typename... Args>
void Print(const char* Text, Args... args)
{
    std::vector<std::string> ArgumentList;
    std::function<void(Args... A)> Unpack = [&] (Args... A)
    {
        auto l = {(ArgumentList.push_back(std::to_string(A)), 0)...};
    };

    Unpack(args...);

    for (auto it = ArgumentList.begin(); it != ArgumentList.end(); ++it)
        std::cout<<*it<<"\n";
}

It uses a Lambda to unpack and push each argument into the vector (I used the lambda to avoid recursive empty template functions; I prefer the nested lambda). However, it needs to use std::to_string(..) because the vector accepts only strings. Thus when I do:

Print("%", "One", "Two", 5);

It does not compile because "One" and "Two" are already literals and std::to_string only takes integral types.

How can I figure out what type of "argument" is being passed? I tried:

template<typename T>
struct is_literal
{
    enum {value = false};
};

template<>
struct is_literal<TCHAR>
{
    enum {value = true};
};

template<>
struct is_literal<TCHAR*>
{
    enum {value = true};
};

template<>
struct is_literal<const TCHAR*>
{
    enum {value = true};
};

template<typename Char, typename Traits, typename Alloc>
struct is_literal<std::basic_string<Char, Traits, Alloc>>
{
    enum
    {
        value = true
    };
};

But realized I couldn't use it on the argument because it's not a template parameter?

I wanted to do:

std::function<void(Args... A)> Unpack = [&] (Args... A)
    {
        auto l = {(ArgumentList.push_back(is_literal<A>() ? A, std::to_string(A)), 0)...};
    };

Which tests if it's literal but it's not right. How can I fix it and test if each argument is a literal?

Upvotes: 0

Views: 110

Answers (1)

catscradle
catscradle

Reputation: 1719

You can define a version of to_string of your own:

std::string to_string(const char* s) {
    return s;
}

And then change your lambda body to:

using namespace std;
auto l = {(ArgumentList.push_back(to_string(A)), 0)...};

Edit: Actually, it's probably better to just define your to_string inside std:

namespace std {
    std::string to_string(const char* s) {
        return s;
    }
}

Upvotes: 2

Related Questions