是否可以将一组值传递给可变参数模板声明,类似于解决斐波纳契数列的方式

时间:2015-08-04 18:14:40

标签: c++ templates c++11 variadic-templates

我正在寻找一个带模板的解决方案,它允许我将值作为模板参数传递,就像通过专门化具有特定数据类型的模板一样。对于前。

template <std::string... Args>
struct MOptional
{
    MOptional()
    {
        possibilities.push_back(std::forward(Args)...);
    }

    std::vector<std::string> possibilities;
};

我想要使用它的方式是这样的。

MOptional<"string1", "string2", "string3"> optional;

因此类中的可能性字段应自动填充string1,string2和string3。我知道我可以用构造函数来做,但我正在寻找类似上面的东西。我希望字符串的数量是可变的。

显然,这段代码并没有编译,只是为了表达我的想法......

任何想法?

最终解决方案(由Barry编辑)

template <typename T, T... Args>
struct MOptional
{
    MOptional()
    {
        // enum { N = sizeof...(Args) };
        T arr[] = { Args... };
        possibilities.assign(std::begin(arr), std::end(arr));
    }

    std::vector<T> possibilities;
};

2 个答案:

答案 0 :(得分:2)

您不能拥有string模板参数,但是您可以使用可以具有的任何类型作为模板非类型参数执行您想要的操作:

template <typename T, T... Args>
struct MOptional
{
    MOptional()
    : possibilities{Args...}
    { }

    std::vector<T> possibilities;
};

例如,int s:

MOptional<int, 1, 2, 3> mo;
std::cout << mo.possibilities.size(); // prints 3

由于MSVC在可变参数模板支持上略微落后,因此可以改为:

MOptional() {
    T arr[] = {Args...};
    possibilities.assign(std::begin(arr), std::end(arr));
}

答案 1 :(得分:0)

无法使用字符串或其他对象作为模板参数。我成功的做法是使用c-string的constexpr哈希。这是看起来像:

/**
* @brief Hashes a given c-string using the FNV-1a standard hash.
* @details This is used eg. to use strings as template arguments.
*/
constexpr uint64_t template_hash(const char* x) {
    return *x ? (uint64_t(*x) ^ template_hash(x+1))*1099511628211ul : 14695981039346656037ul;
}

template<uint64_t hash> struct foo { static uint64_t bar() { return hash;} };

int main() {
    std::cout << foo<template_hash("test")>::bar() << std::endl;
}

应该工作得很好。显然,这不允许您检索字符串,但您可以根据字符串区分类。通过修改哈希,您可以在模板参数中编码一个8-10个字母的字符串,但是对于更多,您将需要在...中进行一些工作... 如果你真的需要8个字符的版本:

constexpr uint64_t template_string(const char* x) {
    return *x ? (uint64_t(*x) | (template_string(x+1)<<8)) : 0ul;
}

我会留给你解码那个字符串。