【问题标题】:Why don't optional parameters work with templates?为什么可选参数不适用于模板?
【发布时间】:2012-09-23 18:15:53
【问题描述】:

为什么带有模板函数的可选参数在 C++ 中不起作用?

(澄清:我希望了解为什么 C++ 被设计成这样是不可能的。)

#include <iostream>
template<class T1, class T2> T1 inc(T1 v, T2 u = 1) { return v + u; }
int main() { std::cout << inc(5); }

prog.cpp: 在函数‘int main()’ 中:错误:没有匹配函数调用‘inc(int)’

【问题讨论】:

  • 您可以在 C++11 中将 T2 默认为 int
  • @chris:是的,但我并不总是使用 C++11。 :\
  • 那么,问题是为什么它在 C++98 中不起作用?考虑到您可以添加重载template &lt;typename T1&gt; T1 inc(T1 v) { return v+1; },我认为原因是“没有实质性的好处”。 C++98 已经很晚了,这样的小事不会再耽搁了。

标签: c++ templates optional-parameters


【解决方案1】:

你弄错了。默认参数不参与参数推导:

参数推导发生首先,作为选择所需重载的一部分,然后在必要时填充该重载的默认参数。

【讨论】:

  • 嗯,是的,这就是错误所暗示的......但为什么呢?这是为了防止一些错误吗? (我在想一些事情,如果默认值不依赖于模板参数,那么它可以被推断为好像它被提供了......)
  • 我认为模板推导和重载解析的规则已经方式太复杂了,没有人想在这里添加另一个特殊情况。您始终可以添加另一个转发到 inc(v, 1) 的重载。
  • 这只是应用规则的方式......它们不是递归或迭代的。您首先进行重载解析,然后进行函数调用(包括填充默认参数)。这就是语言的设计方式。如果您有为什么语言设计是这样的问题,您应该提出一个单独的问题或编辑您的问题以表明这一点。
  • @BoPersson:哦,我明白了......是的,转发在“不错”的情况下工作,但对其他人来说很烦人。
【解决方案2】:

Kerrek SB 所说的是正确的,编译器只是没有足够的能力来推断 T2(根据标准允许的情况)。

在这种特殊情况下,您可能可以通过对所有内容仅使用一个模板参数来修复它,即

template< class T > T inc( const T v, const T u = 1 ) { return v + u; }

【讨论】:

    【解决方案3】:

    默认参数不参与推导过程(仅用于重载解析,并且规则很难记住 - 始终保持简单)。

    为了实现你想要的,你可以提供一个额外的重载:

    template <class T1, class T2> T1 inc(T1 v, T2 u) { return v + u; }
    template <class T> T inc(T v) { return v + T(1); }
    

    【讨论】:

      【解决方案4】:

      C++ 中的模板函数在编译时生成,并且仅在需要时生成。所以你可以得到一个像这样生成的函数:

      inc( int, int );
      

      这将是 T1 = int 和 T2 = int 版本。如果您为每个模板参数传入参数,编译器可以隐式确定类型,因此:

      int a = 1;
      int b = 2;
      inc( a, b );
      

      编译器可以在编译时生成与上述类似的函数,因为它可以推断出 T1 = int 和 T2 = int。但是,如果你做你正在做的事情:

      inc( 5 );
      

      编译器可以确定 T1 = int,但无法确定 T2 是什么。因此不会生成任何函数,并且您会收到有关该函数不存在的错误。如果您使用一个模板参数,这可能是可以解决的:

      template<class T> T inc(T v, T u = 1) { return v + u; }
      

      或者如果你提供了一个重载:

      template<class T> T inc(T v) { return v + 1; }
      

      还有第三种方式:

      inc<int, int>( 5 );
      

      但我想这不是你想要的......

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-11-11
        • 1970-01-01
        • 1970-01-01
        • 2021-03-31
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多