Why isn't argument deduction allowed in functi

2020-07-10 06:05发布

The most obvious answer could be - because the standard says so.
That's fine, but I'm wrapping my head around it to understand the reasons behind this choice.

Consider the following example:

template<typename T>
struct S { S(T) {} };

S f() { return 0; }

int main() {
    auto s = f();
    (void)s;
}

It fails to compile with errors like:

error: use of class template 'S' requires template arguments; argument deduction not allowed in function return type

Quite easy to fix, it isn't a problem, something like this works just fine:

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

However, I'd like to understand what were the drawbacks of allowing class template arguments deduction also in function return types.
At a first glance, it looks just like a silly limitation, but I'm pretty sure I'm missing something important here.

3条回答
Melony?
2楼-- · 2020-07-10 06:41

Why isn't argument deduction allowed in function return type?

Because the standard says so.

You could ask the question: why is there a difference between these lines of code:

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

You could come up with a handwavy explanation of why the first one should be okay and why the second one should not be - but fundamentally class template argument deduction was proposed to only address the first case and not the second. The first one is okay because the standard says so, and the second one is an error because the standard says so.

There is an extension proposed (P1021, under "Return type deduction for functions") that would address the second case. Whether or not you think this is a good idea... ¯\_(ツ)_/¯

查看更多
霸刀☆藐视天下
3楼-- · 2020-07-10 06:55

Just my hand-wavy two cents that summarize my understanding:

In

S f() { return 0; }

the S is no type that could be deduced, its just a template. You could write

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

but now it is obvious that for a call

auto s = f();

there is no way to deduce what type T is supposed to be.

查看更多
够拽才男人
4楼-- · 2020-07-10 07:03

There's nothing language-lawery here: If you specify a return type (and not auto or T where T is a template type), that return type has to be valid. let me give you even a simpler, better example:

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

Obviously it fails to compile, even without fancy templates, auto and type deductions, because std::vector isn't a type, std::vector<int> is.

When you specify S as a return type you basically

  • Prevent the compiler from deducing the type itself
  • Specify an invalid return type, as S isn't a type, S<int> is.
查看更多
登录 后发表回答