简体   繁体   English

默认推导 class 模板参数

[英]Deduce class template parameter with default

I'd like to have a class template with parameters with and without defaults.我想要一个带有和不带默认参数的 class 模板。 And I'd like a parameter with a default to be able to be deduced from the constructor.而且我希望能够从构造函数中推导出一个具有默认值的参数。 An example:一个例子:

template <typename T, typename Compare = std::less<T> >
struct foo {
    foo(const Compare& c = Compare{}) { }
};

foo<int> x;                      // Works, c = std::less<int>{}

foo<int, std::greater<int>> y;   // Works, c = std::greater<int>{}

auto cmp = [](const int&, const int&){ return true; };
foo<int, decltype(cmp)> z(cmp);  // Works (with C++20), c = cmp

foo<int> bad(cmp); // Fails

The issue with the bad code seems to be that since only template parameter T is provided, the default of std::less<int> is used for Compare .错误代码的问题似乎在于,由于只提供了模板参数T ,因此默认std::less<int>用于Compare This makes the constructor's signature foo(const std::less<int>&) , which is not compatible with the call of foo(<lambda>) , as the lambda can't be converted to std:less<int> .这使得构造函数的签名foo(const std::less<int>&)foo(<lambda>)的调用不兼容,因为 lambda 无法转换为std:less<int>

If another argument is added to the constructor, so that all template parameters can be deduced from constructor arguments, then it works.如果在构造函数中添加另一个参数,以便可以从构造函数 arguments 推导出所有模板参数,则它可以工作。

template <typename T, typename Compare = std::less<T> >
struct bar {
    bar(T, const Compare& c = Compare{}) { }
};
bar z2(int{}, [](){return true;});

While it might seem the issue is that the default value for the Compare parameter is taking precedence over what could be deduced, that's not the case.虽然问题似乎是Compare参数的默认值优先于可以推断的值,但事实并非如此。

The real issue is this:真正的问题是这样的:

Class template argument deduction is only performed if no template argument list is present. Class 模板参数推导仅在不存在模板参数列表时执行。 If a template argument list is specified, deduction does not take place.如果指定了模板参数列表,则不会进行推导。

Once a single template parameter is specified, no deduction will take place.一旦指定了单个模板参数,就不会进行任何扣除。 Even though it would seem it is still possible to determine what the remaining template parameters would be.即使看起来仍然可以确定剩余的模板参数是什么。

Without a default value for a template parameter, the compiler with fail earlier with an diagnostic about an incorrect number of template parameters.如果没有模板参数的默认值,编译器会提前失败,并诊断出模板参数数量不正确。 So this limitation can not be observed without also using default values for template parameters.因此,如果不使用模板参数的默认值,则无法观察到此限制。

In summary, at instantiation, class template parameters must be fully known.总之,在实例化时,必须完全知道 class 模板参数。 This can be done by (in order of priority if more than one applies):这可以通过以下方式完成(如果有多个应用,则按优先级顺序):

  1. Fully specifying all parameters.完全指定所有参数。
  2. Specifying no parameters, if all parameters can be deduced.如果可以推导出所有参数,则不指定参数。
  3. Specifying no or some parameters, if all unspecified parameters have defaults.如果所有未指定的参数都有默认值,则不指定或指定一些参数。

These options are not allowed:不允许使用以下选项:

  • Specifying some parameters, if all unspecified parameters can be deduced.指定一些参数,如果可以推导出所有未指定的参数。
  • Specifying some parameters, if all unspecified parameters can be deduced or have a default value.指定一些参数,如果所有未指定的参数都可以推导出或具有默认值。

make_foo works. make_foo有效。

template,class T>
struct tag_t{};
template<class T>
constexpr tag_t<T> tag={};

template <typename T, typename Compare = std::less<T> >
struct foo {
  foo(tag_t<T>, const Compare& c = Compare{}) { }
  foo(const Compare& c = Compare{}) { }
};

also works:也有效:

foo f(tag<int>, cmp);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM