Problem with calling a variadic function template when passing brace initialiser list arguments

后端 未结 3 1768
一个人的身影
一个人的身影 2021-01-01 21:18

Consider this function template:

template 
void foo (std::tuple ... x);

This invocation works:

3条回答
  •  借酒劲吻你
    2021-01-01 21:27

    Generate an overloaded set of constructors:

    #include 
    #include 
    
    template 
    using indexed = T;
    
    template 
    struct initializer : initializer
    {    
        using initializer::initializer;
    
        initializer(indexed... ts)
        {
            // ts is a pack of std::tuple
        }
    };
    
    template 
    struct initializer {};
    
    using foo = initializer, 20>;
    //                                   tuples limit+1 ~~~^
    
    int main()
    {
        foo({1,'2',3.0});
        foo({1,'2',3.0}, {4,'5',6.0});
        foo({1,'2',3.0}, {4,'5',6.0}, {7,'8',9.0});
    }
    

    DEMO


    Generate an overloaded set of function call operators:

    #include 
    #include 
    
    template 
    using indexed = T;
    
    template 
    struct initializer : initializer
    {    
        using initializer::operator();
    
        int operator()(indexed... ts) const
        {            
            // ts is a pack of std::tuple
            return 1;
        }
    };
    
    template 
    struct initializer
    {
        int operator()() const { return 0; }
    };
    
    static constexpr initializer, 20> foo = {};
    //                                        tuples limit+1 ~~~^
    
    int main()
    {    
        foo({1,'2',3.0});
        foo({1,'2',3.0}, {4,'5',6.0});
        foo({1,'2',3.0}, {4,'5',6.0}, {7,'8',9.0});
    }
    

    DEMO 2


    Create (or generate with preprocessor macros) a set of overloads that forward arguments to a single implementation:

    #include 
    #include 
    
    using K = std::tuple;
    
    void foo(const std::array& a)
    {
        // a is an array of at most 5 non-null std::tuple*
    }
    
    void foo(K p0) { foo({&p0}); }
    void foo(K p0, K p1) { foo({&p0, &p1}); }
    void foo(K p0, K p1, K p2) { foo({&p0, &p1, &p2}); }
    void foo(K p0, K p1, K p2, K p3) { foo({&p0, &p1, &p2, &p3}); }
    void foo(K p0, K p1, K p2, K p3, K p4) { foo({&p0, &p1, &p2, &p3, &p4}); }
    
    int main()
    {
        foo({1,'2',3.0});
        foo({1,'2',3.0}, {4,'5',6.0});
        foo({1,'2',3.0}, {4,'5',6.0}, {7,'8',9.0});
    }
    

    DEMO 3


    Pass as an array and deduce its size (requires additional pair of parens):

    #include 
    #include 
    
    template 
    void foo(const std::tuple (&a)[N])
    {
        // a is an array of exactly N std::tuple
    }
    
    int main()
    {
        foo({{1,'2',3.0}, {4,'5',6.0}});
     //     ^~~~~~ extra parens ~~~~~^
    }
    

    DEMO 4


    Use an std::initializer_list as a constructor parameter (to skip extra parens):

    #include 
    #include 
    
    struct foo
    {
        foo(std::initializer_list> li)
        {
            // li is an initializer list of std::tuple
        }
    };
    
    int main()
    {
        foo{ {1,'2',3.0}, {4,'5',6.0} };
    }
    

    DEMO 5

提交回复
热议问题