代码之家  ›  专栏  ›  技术社区  ›  OlimilOops

不使用<>;类型推断调用模板函数

  •  10
  • OlimilOops  · 技术社区  · 15 年前

    如果我有一个函数模板 typename T 如果编译器可以自己设置类型,那么在调用函数时,我不必显式地编写类型,例如:

    template < typename T > 
    T min( T v1, T v2 ) {
       return ( v1 < v2 ) ? v1: v2;
    }
    int i1 = 1, i2 = 2; int i3 = min( i1, i2 ); //no explicit <type> 
    

    但是,如果我有一个具有两个不同类型名的函数模板,例如:

    template < typename TOut, typename TIn >
    TOut round( TIn v ) {
       return (TOut)( v + 0.5 );
    }
    double d = 1.54;
    int i = round<int>(d); //explicit <int>
    

    我总是必须指定至少一个类型名,这是真的吗?我认为原因是因为C++无法区分不同返回类型之间的函数。

    但是,如果我使用void函数并传递引用,那么我就不能显式地指定返回类型名:

    template < typename TOut, typename TIn > 
    void round( TOut & vret, TIn vin ) {
       vret = (TOut)(vin + 0.5);
    }
       double d = 1.54;
       int i; round(i, d); //no explicit <int>
    

    结论应该是避免返回函数和更倾向于返回函数 void 在编写模板时通过引用返回的函数?或者是否有可能避免显式写入返回类型?类似于模板的“类型推断”。C++0x中的“类型推断”是否可能?

    3 回复  |  直到 9 年前
        1
  •  16
  •   Thomas    15 年前

    重载解析仅基于函数参数完成;返回值根本不使用。如果无法基于参数确定返回类型,则必须显式指定它。

    我不会通过引用参数“返回”一个值;这会使调用代码不清楚。例如,我更喜欢这样:

    double x = round<double>(y);
    

    在此之上:

    double x;
    round(x, y);
    

    因为在后一种情况下,很容易混淆输入和输出,而且根本不清楚 x 正在修改。

    在特定情况下 round ,您可能只需要一到两种类型 TOut 不管怎样,所以您可以将模板参数保留在外:

    template<typename TIn>
    int roundToInt(TIn v) {
        return (int)(v + 0.5);
    }
    

    我发现 roundToInt(x) round<int>(x) 因为很明显 int 类型用于。

        2
  •  3
  •   Konrad Rudolph    15 年前

    结论是,在编写模板时,避免使用返回函数,而更喜欢使用通过引用返回的void函数。

    不,为什么?你得到了什么?只进行类型推断(这样编写的代码就更少了)。但是你 失去 分配一个值的逻辑语法要多得多(因此要编写的代码也要多得多)。所以一件事得到了,另一件事失去了。总的来说,我看不到好处。

    甚至可以 帮助 必须显式指定模板类型:考虑 lexical_cast . 如果不指定返回模板类型,将导致混淆。

        3
  •  2
  •   wheaties    15 年前

    让我补充一下其他人所说的,你应该更喜欢C++铸造而不是C风格的铸造。

    vret = (TOut)(vin + 0.5);
    

    对战

    vret = static_cast<TOut>(vin + 0.5);
    

    如果尝试转换不相关的类型,静态强制转换将始终失败。这有助于调试。