首页 > 解决方案 > 在 C++-17 中,此构造函数是否有模板推导指南?

问题描述

是否有模板推导指南可以将变量c推导出为类型bar<baz>,就像变量一样b

#include <vector>
#include <functional>

template<typename T>
struct foo {
  using container = std::vector<T>;
  using creator = std::function<container()>;
};

template<typename T>
struct bar
{
    bar(typename foo<T>::creator) { }
};

struct baz : public foo<baz> {
  static baz::container make_it() { return {}; }
};

int main() {
    bar<baz> b(baz::make_it);
    bar c(baz::make_it); // What is the deduction guide to mimic b?
}

标签: c++c++17

解决方案


这里的困难是由于参数和被推导的类型之间的关系非常脆弱。由于对函数参数的不必要限制,它也是不必要的。

我看不出你为什么特别需要在std::function这里参加。您已经在模板中;您可以采用任何可调用类型,只要它可以用零参数调用并返回适当类型的容器。所以……就那样做吧。

即使类型要在std::function内部存储 a,构造函数也可以自己执行转换,而不是将其塞入函数签名中。

一旦构造函数看起来像这样:

template<typename T>
struct bar
{
    template<typename Func>
    bar(Func &&f) { }
};

然后可以编写一个演绎指南来创建关于 和 之间关系的Func期望T。即:

template<typename Func>
bar(Func &&f) -> bar<std::invoke_result_t<Func>::value_type>;

这对任何可调用类型都有效,这些类型可以存储在std::function<container()>.


但是,如果您不愿意使您的代码更合理地通用,您仍然可以这样做。事实上,上面的推导指南可以正常工作......只要你没有其他只接受一个参数的构造函数。那你就会有问题。

让您感到困惑的部分是foo. 所以摆脱它并列出你实际在做什么。您的构造函数采用 a std::function,可以使用零参数调用它以返回一个vector纯右值,它value_type是您要推断的类型。所以就这么说吧:

template<typename T>
bar(std::function<vector<T>()>) -> bar<T>;

是的,你必须重复你的定义baz::container,但它有效。不,您不需要将匹配的构造函数设为模板。

事实上,你甚至不需要扣除指南:

template<typename T>
struct bar
{
    bar(std::function<vector<T>()>) { }
};

推荐阅读