Converting Variadic template pack into std::initializer_list

后端 未结 3 1812
盖世英雄少女心
盖世英雄少女心 2021-02-03 11:52

Assume that there is a function which accepts several strings:

void fun (const std::initializer_list& strings) {
  for(auto s : strings)
          


        
3条回答
  •  陌清茗
    陌清茗 (楼主)
    2021-02-03 12:36

    Here's an answer to both points:

    #include 
    #include 
    #include 
    #include 
    
    using namespace std;
    
    void fun (const std::initializer_list& strings) {
      for(auto s : strings)
        cout << s << endl;
    }
    
    // This uses SFINAE to find if there's a string T::value in T
    template 
    struct HasValue
    {
        typedef char OK; //sizeof() guaranteed 1
        struct BAD { char x[2]; }; //sizeof() guaranteed >1
    
        template 
        struct Helper;
    
        template 
        static OK has(X*, Helper<&X::value>* = nullptr); //SF if &X::value is not a const string*
    
        static BAD has(...);  //will be picked in SF case
    
        static const bool value = (sizeof(has((T*)nullptr)) == sizeof(OK));
    };
    
    
    // This template (and its specialisation) ensure all args have ::value
    template 
    struct HaveValue : public integral_constant::value && HaveValue::value>
    {};
    
    template 
    struct HaveValue : public HasValue
    {};
    
    
    
    template 
    void foo() {
        static_assert(HaveValue::value, "All arguments must have const string ::value");
        fun({Args::value...});  //answer to point 2: create the initialiser list
    }
    
    // Example data follow
    struct A
    {
        static const string value;
    };
    const string A::value = "AA";
    
    struct B
    {
        static const string value;
    };
    const string B::value = "BB";
    
    struct C{};
    
    int main()
    {
        foo();
        //foo();  //uncomment to have the static assertion fire
    }
    

    See it live.

提交回复
热议问题