c++ - Converting Variadic template pack into std::initializer_list -


assume there function accepts several strings:

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

now, have variadic template function foo() as:

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

this method called externally as:

foo<a, b, c, d>(); // a, b, c, d classes 

and these classes passed arguments expected contain common static const member:

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

here questions (how to):

  1. when inside foo(), check if args contain value using static_assert
  2. pass such values fun() form initializer_list; e.g. fun({a::value, b::value, ...});

searched several threads related variadic templates , unpacking still novice in area. explanation in little more detail appreciated.

as second question, way:

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

the mechanism pretty intuitive: create initalizer list contains expanded args::value pattern, resolving (in case) { a::value, b::value, c::value, d::value }.

here complete program:

#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 { 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>(); // a, b, c, d classes } 

and here live example.

as static assertion, may write type trait determines whether type has 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, use 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...}); } 

here live example of successful check (all classes has value data member). here live example of unsuccessful check (class d's data member called values)


Comments

Popular posts from this blog

c# - Operator '==' incompatible with operand types 'Guid' and 'Guid' using DynamicExpression.ParseLambda<T, bool> -