是否可以使用lambda函数扩展参数包?

时间:2017-08-20 23:43:34

标签: c++ c++11 templates variadic-templates

我认为我的问题是一个极端的案例,你可以用参数包扩展到多远,而且有点难以解释,我想要什么。这个想法最容易用一些代码表达,所以让我们看看以下几行:

// <main.cpp>
#include <tuple>
#include <iostream>

// this function is supposed to return a std::tuple of function objects
// for each template argument type, there should be one such function object,
// that takes a value of this type and returns its half.
template <class... arg_t>
auto make_divide_by_two_lambda_tuple() {
    return std::make_tuple(
        [](const arg_t& elem) -> arg_t
        {
            return elem/2;
        }...
    );
}

int main()
{
    // lets initialise a tuple with our function
    auto value = make_divide_by_two_lambda_tuple<int, float>();

    /*
     * If everything workes as planned, the tuple has this structure
     * value<0> := [](const int&){ ... }
     * value<1> := [](const float&){ ... }
     */

    // and we are able to use our functions in the expected way
    std::cout << "5/2 (int version) = " << std::get<0>(value)(5) << std::endl;
    std::cout << "5/2 (float version) = " << std::get<1>(value)(5) << std::endl;

    return 0;
}

对于clang(4.0.1),此示例按照我的预期编译并运行:

$ clang++ -std=c++14 ../main.cpp
$ ./a.out 
5/2 (int version) = 2
5/2 (float version) = 2.5

对于g ++(7.1.1),此示例无法编译:

$ g++ -std=c++14 ../main.cpp    
../main.cpp: In function ‘auto make_divide_by_two_lambda_tuple()’:
../main.cpp:7:28: error: parameter packs not expanded with ‘...’:
   [](const arg_t& elem) -> arg_t
                            ^~~~~
../main.cpp:7:28: note:         ‘arg_t’
../main.cpp:7:28: error: parameter packs not expanded with ‘...’:
../main.cpp:7:28: note:         ‘arg_t’
../main.cpp:10:4: error: expansion pattern ‘<lambda>’ contains no argument packs
   }...
    ^~~
../main.cpp: In function ‘int main()’:
../main.cpp:15:10: error: ‘void value’ has incomplete type
     auto value = make_divide_by_two_lambda_tuple<int, float>();

看来,gcc愿意在lambda表达式的参数列表中使用参数包。但是使用整个lambda对于gcc来说太过分了。

这是使用lambda表达式未定义的行为,还是一个编译器(希望是gcc)错了?

PS:我还检查了docs,但它只解释了,您可以在哪里使用参数包扩展,而不是您可以扩展的哪些参数。

0 个答案:

没有答案