是否可以将一组值传递给可变参数模板声明,类似于斐波那契数列的求解方式
Is it possible to pass a set of values to a variadic template declaration similar to how the fibonacci series is solved
我正在寻找一个带有模板的解决方案,它允许我将值作为模板参数传递,就像通过使用特定数据类型专门化模板所做的那样。例如
template <std::string... Args>
struct MOptional
{
MOptional()
{
possibilities.push_back(std::forward(Args)...);
}
std::vector<std::string> possibilities;
};
我想要的使用方式是这样的。
MOptional<"string1", "string2", "string3"> optional;
因此 class 中的可能性字段应该自动填充字符串 1、字符串 2 和字符串 3。我知道我可以用构造函数来做,但我正在寻找类似上面的东西。我希望字符串的数量是可变的。
显然这段代码无法编译,只是为了传达我想要的...
有什么想法吗?
最终解决方案(由 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;
};
你不能有 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));
}
无法使用字符串或其他对象作为模板参数。不过,我成功完成的是使用 c 字符串的 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;
}
我会把它留给你来解码那个字符串。
我正在寻找一个带有模板的解决方案,它允许我将值作为模板参数传递,就像通过使用特定数据类型专门化模板所做的那样。例如
template <std::string... Args>
struct MOptional
{
MOptional()
{
possibilities.push_back(std::forward(Args)...);
}
std::vector<std::string> possibilities;
};
我想要的使用方式是这样的。
MOptional<"string1", "string2", "string3"> optional;
因此 class 中的可能性字段应该自动填充字符串 1、字符串 2 和字符串 3。我知道我可以用构造函数来做,但我正在寻找类似上面的东西。我希望字符串的数量是可变的。
显然这段代码无法编译,只是为了传达我想要的...
有什么想法吗?
最终解决方案(由 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;
};
你不能有 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));
}
无法使用字符串或其他对象作为模板参数。不过,我成功完成的是使用 c 字符串的 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;
}
我会把它留给你来解码那个字符串。