自动扣除别名模板和模板类的模板参数

时间:2015-10-21 16:31:49

标签: c++ templates c++11 c++14 type-deduction

我想使variadic模板参数列表的无状态lambda函数是递归的。但我需要类型擦除以避免像variable 'lambda' declared with 'auto' type cannot appear in its own initializer这样的错误。可变参数模板参数列表需要相应的功能对象具有模板operator ()。对于简单的无状态lambda函数,我可以将它转换为指向简单的自由旧函数,但是如何实现类似于 variadic 无状态lambda函数?我想我想要的是模板参数列表的自动类型推导(在模板变量的实例化期间:在调用期间或在赋值期间):(伪代码)

#include <type_traits>
#include <iostream>

#include <cstdlib>

template< typename first, typename second, typename ...rest >
using fp = first (*)(first const &, second const &, rest const &...); // at least binary function

int
main()
{
    template fp sum = [] (auto const & first, decltype(first) second, auto const &... rest) { return first + sum(second, rest...); };
    //              ^ assignment                                                                                ^ call
    std::cout << sum(1, 2.0, 3.0f) << std::endl;
    return EXIT_SUCCESS;
}

目前是否有可能实现这样的行为( C ++ 14 )(例如,使用std::function或其他类型的擦除方式)?是否有类似语言功能的提议?或者它可能完全被已经存在的语言规则所禁止?

另一个有用的例子:(伪代码)

template std::vector v{1, 2, 3};
static_assert(std::is_same< decltype(v), std::vector< int > >{});

1 个答案:

答案 0 :(得分:3)

不,没有办法做你想做的事。推断表达式结果的方法是使用auto。无法推断出函数模板或别名模板的类型。考虑最简单的情况:

std::function<auto> if_this_existed = [](int x, int y) { return x + y; };

您可能期望std::function<int(int, int)>。但std::function<void(int, int)>有效。 std::function<long(long, long)>也是如此。真的没有一件事可以推断。此外,对于泛型 lambda,分配特定的类型没有意义:

std::function<void(???)> print = [](auto x) { std::cout << x; };

可以使用任何可打印的类型调用lambda,但是我们在???中放置的任何内容都会将print限制为该类型。所以这也失败了。

所以最终,不,你不能递归地编写你的通用可变参数lambda。虽然,sum无论如何都不可能递归写,因为你不能写一个基本案例。编写这样的通用sum()的正确方法是使用折叠表达式(C ++ 1z):

auto sum = [] (auto const&... args) {
    return (args + ...);
};