将Variadic模板包转换为std :: initializer_list

iam*_*ind 10 c++ templates initializer-list variadic-templates c++11

假设有一个接受多个字符串的函数:

void fun (const std::initializer_list<std::string>& strings) {
  for(auto s : strings)
    // do something
}
Run Code Online (Sandbox Code Playgroud)

现在,我有一个可变template函数说foo():

template<typename ...Args>
void foo () {
  fun(???);
}
Run Code Online (Sandbox Code Playgroud)

此方法在外部称为:

foo<A, B, C, D>(); // where A, B, C, D are classes
Run Code Online (Sandbox Code Playgroud)

这些作为参数传递的类应该包含一个公共static const成员:

static const std::string value = "...";
Run Code Online (Sandbox Code Playgroud)

以下是我的问题(如何):

  1. 在里面foo(),检查是否所有Args包含value使用 static_assert
  2. 将所有这些值传递fun()给形成initializer_list; 例如 fun({A::value, B::value, ...});

搜索了几个与可变参数模板及其解包相关的线程,但我仍然是这个领域的新手.非常感谢更详细的解释.

And*_*owl 7

至于第二个问题,就这样做:

template<typename ...Args>
void foo () {
  fun({Args::value...});
}
Run Code Online (Sandbox Code Playgroud)

该机制非常直观:您创建一个包含扩展Args::value模式的初始化列表,从而解析(在您的情况下){ A::value, B::value, C::value, D::value }.

这是一个完整的程序:

#include <string>
#include <iostream>

void fun (const std::initializer_list<std::string>& strings) {
    for(auto s : strings)
    {
        std::cout << s << " ";
    }
}

template<typename ...Args>
void foo () {
  fun({Args::value...});
}

struct A { static std::string value; };
struct B { static std::string value; };
struct C { static std::string value; };
struct D { static std::string value; };

std::string A::value = "Hello";
std::string B::value = "World";
std::string C::value = "of";
std::string D::value = "Variadic Templates";

int main()
{
    foo<A, B, C, D>(); // where A, B, C, D are classes
}
Run Code Online (Sandbox Code Playgroud)

这是一个实例.

至于静态断言,您可以编写一个类型特征来确定某个类型是否具有成员变量value:

template<typename T, typename V = bool>
struct has_value : std::false_type { };

template<typename T>
struct has_value<T,
    typename std::enable_if<
        !std::is_same<decltype(std::declval<T>().value), void>::value,
        bool
        >::type
    > : std::true_type
{
    typedef decltype(std::declval<T>().value) type;
};
Run Code Online (Sandbox Code Playgroud)

然后,您可以这样使用它:

template<typename T>
struct check_has_value
{
    static_assert(has_value<T>::value, "!");
};

template<typename ...Args>
void foo () {
    auto l = { (check_has_value<Args>(), 0)... };
    fun({Args::value...});
}
Run Code Online (Sandbox Code Playgroud)

以下是成功检查的实例(所有类都有value数据成员).这是一个不成功检查的实例(D调用类的数据成员values)