Search code examples
c++initializer-listperfect-forwarding

Template argument deduction for initializer_list with forwarding


I want to use perf. forwarding with initializer_list (curly braces), but I've failed in writing code that could be compiled.

How to make type deduction working in the following sample of code?

#include <utility>

template <class _T> struct B {
    _T a;
    _T b; };

template <class _T> void bar(B<_T>&& a) {}

template <class _T> void bar(B<_T>& a) {}

template <class _T> struct A {
    template <class __T>
    void foo(__T&& a) {
        bar(std::forward<__T>(a));
    } };

int main() {
    A<int> a;
    a.foo({1, 3}); }

I know that it's possible to do perfect forwarding with variadic template argument, like this:

#include <utility>

template <class _T>
struct B {
    _T a;
    _T b;
};

template <class _T>
void bar(_T&& v1, _T&& v2) {
    B<_T> b{v1, v2};
}

template <class _T>
void bar(_T& v1, _T& v2) {
    B<_T> b{v1, v2};
}

template <class _T>
struct A {
    template <class... Args>
    void foo(Args&&... args) {
        bar(std::forward<Args>(args)...);
    }
};

int main() {
    A<int> a;
    a.foo(1, 3);
}

But I want to call foo with cutee curly braces.


Solution

  • {1, 3} has no type, so cannot be deduced for "generic" template type.

    You might use overload with std::initializer_list to handle it;

    template <class T>
    struct A {
        template <class U>
        void foo(U&& a) {
            bar(std::forward<U>(a));
        }
    
        template <class U>
        void foo(std::initializer_list<U> a) {
            bar(a); // assuming bar(std::initializer_list<U>)
        }
    
    };
    
    int main() {
        A<int> a;
        a.foo({1, 3});
    }