【问题标题】:Automatic deduction of template parameters for alias templates and template classes自动扣除别名模板和模板类的模板参数
【发布时间】:2015-10-21 16:31:48
【问题描述】:

我想让带有可变参数模板参数列表的无状态 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 > >{});

【问题讨论】:

  • 你能发布示例代码来触发你提到的错误variable 'lambda' declared with 'auto' type cannot appear in its own initializer 吗?
  • @m.s. auto lambda = [] (auto const &amp; first, decltype(first) second, auto const &amp;... rest) { return first + lambda(second, rest...); }; 这里的 lambda 变量应该默认按值捕获([&amp;][&amp;lambda] 也是如此)。
  • 对于第二个例子,Template parameter deduction for constructors (Rev. 3) 可能会有所帮助。

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


【解决方案1】:

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

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

您可能期望std::function&lt;int(int, int)&gt;。但是std::function&lt;void(int, int)&gt; 有效。 std::function&lt;long(long, long)&gt; 也是如此。真的没有什么可以推断的。此外,对于 generic lambda,分配 specific 类型是没有意义的:

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

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

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

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

【讨论】:

  • 真正的基本情况是我的遗漏,但第二个例子呢?
  • @Orient 我不知道你的第二个例子是什么意思。
  • 第二个例子意味着std::vector的第一个模板参数应该被推导出来,std::initializer_list构造函数是可行的。
  • @Orient 这没有任何意义。
  • 这是一个有争议的结论。
猜你喜欢
  • 2017-01-20
  • 2014-01-29
  • 2018-08-26
  • 2019-11-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多