将Variadic模板包转换为std :: initializer_list [英] Converting Variadic template pack into 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):
- 在
foo()
中时,检查所有Args
是否包含值
使用
static_assert
- 将所有此类值传递给
fun()
形成initializer_list
;例如
fun({A :: value,B :: value,...});
- When inside
foo()
, check if all theArgs
containvalue
usingstatic_assert
- Pass all such values to
fun()
to form aninitializer_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屋!