在Visual Studio 2015中扩展lambda中的参数包:错误C3546

Parameter pack expansion in a lambda with Visual Studio 2015: error C3546

本文关键字:参数 C3546 错误 lambda Visual Studio 2015 扩展      更新时间:2023-10-16

在这个问题之后,我尝试编译以下代码:

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

这在gcc中可以正常工作,但在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>'

看起来像当符号...没有绑定到参数包(?)时,可视化编译器扩展失败

有办法解决这个问题吗?

下面是生成错误的最小示例:
#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;
}

我最终用一个结构替换了for_each函数:

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)... };
    }
};

稍微修改一下用法:

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;
}