为什么decltype不是隐式的?

9
为什么在期望类型时无法隐式添加decltype表达式?
template <class X, class Y, class Z>
auto foo(X x, Y y, Z z){
    std::vector<decltype(x+y*z)> values;  // valid in c++11/c++14
    //std::vector<x+y*z> values;            // invalid
    values.push_back(x+y*z);
    return values;                        // type deduced from expression - OK
}

在C++14编译器中,将能够根据返回表达式推断函数的返回类型。为什么不能将其扩展到任何“表达式->类型”转换?
对于declval也是如此,为什么我必须写:
std::vector<decltype(declval<X>() + declval<Y>() * declval<Z>())> values;

改为:

std::vector<X+Y*Z> values;

3
我很确定这可能会引入模棱两可的解析... - Jarod42
3
为了获得微小的好处,就引入了许多隐含的东西在 C++ 中。显式 = 好,隐式 = 差。 - jrok
7
@jrok:这太泛泛而谈了。或者你想要使用汇编语言编码吗? - Deduplicator
3
@Deduplicator 请运用常识 :) 实际上,我不喜欢过度概括自己。 - jrok
5
@Deduplicator:你把明确和低级混淆了。如果忽略C++,Rust在显式 vs 隐式的比例上采取了一种相当极端的观点(例如即使在非丢失上下文中也要进行显式整数转换),但它已经内置了函数式编程概念。 - Matthieu M.
显示剩余6条评论
1个回答

11
如果允许隐式添加decltype,一些非常常见的模板可能会变得模棱两可,甚至无法表达。
考虑以下例子:
struct tp 
{
    template<typename T>
    void foo() { cout << "Type parameter\n"; }   

    template<int Value>
    void foo() { cout << "Value parameter\n"; }   
};

int main() 
{
  const int x = 1;
  const int y = 2;
  const int z = 3;

  tp t1;
  t1.foo<x*y+z>();
  t1.foo<decltype(x*y+z)>(); // Oops ! different version of foo() 
  t1.foo<int>();

  return 0;
}

输出:

值参数

类型参数

类型参数

如果在t1.foo<x*y+z>();中隐含添加了decltype,将调用错误版本的foo()函数。

  • C++ 表达所做之事的策略,并尽可能避免编译器的任何隐式工作,在我看来是非常好的。这使得阅读、理解和维护变得更加容易。
  • 毕竟,decltype只有8个字母

此处可查看演示


7
它们不是“constexpr”,但它们是常量表达式。 - jrok
事实上,在您的示例中,constexpr 被隐式添加到 x、y 和 z。GCC,你竟然敢这样做。 :) - p2rkw
1
@Deduplicator:尽管如此,隐式生成被认为是一个错误,这就是为什么即使在C++11中,如果指定了移动构造函数,复制构造函数(例如)也不会被生成。曾经有讨论过实际上不再自动生成复制构造函数,但这将破坏向后兼容性(C++非常不愿意这样做)......然而,这表明委员会认识到这种隐式生成是“问题”,而不是解决方案。 - Matthieu M.
@Deduplicator:我认为最初的意图是在你偏离C结构时尽快压制它(以保持与C的兼容性);然而,正如提到的那样,这将破坏太多的C++程序,因此它只在移动构造函数/赋值运算符涉及到时才会启动,因为这些显然是C++11(因此是新的)。 - Matthieu M.
1
@p2rkw 不,constexpr关键字并不是自动添加的。你误解了constexpr的含义。constexpr指定一个实体(变量/函数)最好在编译时可访问/计算,它并不是用来说明一个变量/值是常量表达式的关键字。成为常量表达式是值的属性。把constexpr看作是给编译器的提示,类似于“尝试在编译时计算这个”。请注意,例如,在constexpr函数中的参数即使传递的值是常量表达式,也不被视为constexpr - Manu343726
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接