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

为什么函数返回类型中不允许参数推导?

  •  5
  • skypjack  · 技术社区  · 6 年前

    最明显的答案可能是- 因为标准是这样说的 .
    那很好,但我正绞尽脑汁想弄清楚这一选择背后的原因。

    请考虑以下示例:

    template<typename T>
    struct S { S(T) {} };
    
    S f() { return 0; }
    
    int main() {
        auto s = f();
        (void)s;
    }
    

    它无法编译,错误如下:

    错误:使用类模板“s”需要模板参数;函数返回类型中不允许参数推断

    很容易解决,这不是问题,像这样的工作很好:

    auto f() { return S{0}; }
    

    但是,我想了解在函数返回类型中也允许类模板参数推断的缺点。
    乍一看,这似乎是一个愚蠢的限制,但我很肯定我遗漏了一些重要的东西。

    3 回复  |  直到 6 年前
        1
  •  10
  •   David Haim    6 年前

    这里没有语言lawry:如果指定返回类型(而不是 auto T 哪里 T 是模板类型),该返回类型必须有效。让我举一个更简单、更好的例子:

    std::vector function() {
        return std::vector<int>();
    }
    

    显然它无法编译,即使没有花哨的模板, 汽车 并键入扣减,因为 std::vector 不是一种类型, std::vector<int> 是.

    当您指定 S 作为回报类型,你基本上

    • 防止编译器推断类型本身
    • 指定无效的返回类型,如 S 不是一种类型, S<int> 是.
        2
  •  5
  •   Barry    6 年前

    为什么函数返回类型中不允许参数推导?

    因为标准是这么说的。

    S s = 0;            // OK
    S s() { return 0; } // error - even though this is also copy-initializing an "S" from 0
    

    你可以给出一个简单的解释,解释为什么第一个应该是好的,为什么第二个不应该是好的——但是基本上,类模板参数推导是为了只处理第一个情况而不是第二个。第一个是好的,因为标准是这样说的,第二个是错误的,因为标准是这样说的。

    有人提议延期( P1021 ,在“函数的返回类型扣除”)下,这将解决第二种情况。不管你是否认为这是个好主意…()()

        3
  •  4
  •   463035818_is_not_an_ai    6 年前

    只是我的手挥舞着两分钱来总结我的理解:

    S f() { return 0; }
    

    这个 S 不是可以推断的类型,它只是一个模板。你可以写

    template<typename T>
    S<T> f() { return 0;}
    

    但现在很明显

    auto s = f();
    

    无法推断是哪种类型 T 应该是的。