Parameter package extension in lambda with Visual Studio 2015: error C3546

Following this question , I tried to compile the following code:

template<typename... Types>
auto for_each(type_list<Types...>) {
    return [](auto&& f) {
        using swallow = int[];
        (void) swallow { 0, (void(f(tag<Types>{})), 0)... };
    };
}

This works fine with gcc, but generates the following error with visual studio 2015:

main.cpp(19): error C3546: '...': there are no parameter packs available to expand

main.cpp(48): note: see reference to function template instantiation 'auto for_each::<lambda_9a452bac795593df4639d6433fa242d3>::operator ()<main::<lambda_b7b233027d9428cb5ddc16c87ea59d21>>(main::<lambda_b7b233027d9428cb5ddc16c87ea59d21> &&) const' being compiled

main.cpp(18): error C3520: 'Types': parameter pack must be expanded in this context

main.cpp(18): error C2672: 'operator __surrogate_func': no matching overloaded function found

main.cpp(18): error C2893: Failed to specialize function template 'auto main::<lambda_b7b233027d9428cb5ddc16c87ea59d21>::operator ()(_T1) const'

main.cpp(18): note: With the following template arguments:

main.cpp(18): note: '_T1=tag<Types>'

It seems that the visual compiler does not work with the extension if the character is ...not tied to a parameter package (?)

Is there any way to solve the problem?

Here is a minimal example for generating an error:

#include <iostream>
#include <string>

template<typename... > struct type_list {};

template<typename T>
struct tag { using type = T; };

template<typename... Types>
auto for_each(type_list<Types...>) {
    return [](auto&& f) {
        using swallow = int[];
        (void) swallow { 0, (void(f(tag<Types>{})), 0)... };
    };
}

struct A {
    static std::string get_type_name() { return { "A" }; }
};

struct AA : A {
    static std::string get_type_name() { return { "AA" }; }
};

int main() {
    for_each(type_list<A, AA>{}) (
        [&](auto t) {
            using B = typename decltype(t)::type;
            std::cout << B::get_type_name() << std::endl;
        }
    );

    return 0;
}
+4
source share
1 answer

As a result, I replaced the function for_eachwith a structure:

template<typename T> struct for_each {};

template<typename... Types>
struct for_each<type_list<Types...>> {
    template<typename F>
    for_each(F f) {
        using swallow = int[];
        (void) swallow { 0, (f(tag<Types>{}), 0)... };
    }
};

With slightly modified use:

int main() {
    for_each<type_list<A, AA>>{
        [&](auto t) {
            using B = typename decltype(t)::type;
            std::cout << B::get_type_name() << std::endl;
        }
    };

    return 0;
}
0
source

Source: https://habr.com/ru/post/1654206/


All Articles