将Variadic模板包转换为std :: initializer_list [英] Converting Variadic template pack into std::initializer_list

查看:123
本文介绍了将Variadic模板包转换为std :: initializer_list的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Assume that there is a function which accepts several strings:

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

现在,我有一个可变的模板函数,说 foo()如下:

Now, I have a variadic template function say foo() as:

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

此方法在外部被称为:

foo<A, B, C, D>(); // where A, B, C, D are classes

类,这些作为参数传递的类是预期包含一个常见的 static const 成员:

And these classes which are passed as arguments are expected to contain a common static const member:

static const std::string value = "...";

这是我的问题(如何操作):

Here are my questions (how to):


  1. foo()中时,检查所有 Args 是否包含使用
    static_assert

  2. 将所有此类值传递给 fun()形成 initializer_list ;例如
    fun({A :: value,B :: value,...});

  1. When inside foo(), check if all the Args contain value using static_assert
  2. Pass all such values to fun() to form an initializer_list; e.g. fun({A::value, B::value, ...});

搜索了与可变参数模板及其解压缩有关的多个线程,但我仍然是该领域的新手。

Searched several threads related to variadic templates and its unpacking but I am still novice in this area. Explanation in little more detail is much appreciated.

推荐答案

对于第二个问题,只需这样做:

As for the second question, just do it this way:

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

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

The mechanism is pretty intuitive: you create an initalizer list that contains the expanded Args::value pattern, thus resolving (in your case) to { 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
}

实时示例

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

As for the static assertion, you may write a type trait that determines whether a certain type has a member variable 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;
};

然后,您可以通过以下方式使用它:

Then, you could use it this way:

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...});
}

这是成功检查的示例 (所有类的值均 数据成员)。这是一个 实时示例 检查(类 D 的数据成员称为 values

Here is a live example of a successful check (all classes has a value data member). Here is a live example of an unsuccessful check (class D's data member is called values)

这篇关于将Variadic模板包转换为std :: initializer_list的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆