【问题标题】:Why decltype isn't implicit?为什么 decltype 不是隐式的?
【发布时间】:2014-07-27 13:23:28
【问题描述】:

为什么 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;

【问题讨论】:

  • 我很确定它可能会引入模棱两可的解析......
  • ... 几乎没有什么好处。 C++ 中已经有一大堆隐含的东西了。显式 = 好,隐式 = 坏。
  • @jrok:这太笼统了。或者你想在汇编器中编码?
  • @Deduplicator 应用常识 :) 事实上,我不喜欢过度概括自己。
  • @Deduplicator:您将显式误认为是低级。回顾过去的 C++,Rust 在 显式与隐式 尺度上采取了相当极端的观点(例如,即使在非有损上下文中显式整数转换),但它也包含了函数式编程概念。

标签: c++ c++11


【解决方案1】:

如果允许隐式添加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;
}

输出:

值参数

类型参数

类型参数

如果decltype 隐式添加到t1.foo&lt;x*y+z&gt;();,则会调用错误版本的foo()。

  • C++ 策略用于表达你所做的事情,并尽可能避免编译器的任何隐式工作,恕我直言,这是一件非常好的事情。它使事情更易于阅读、理解和维护。
  • 毕竟decltype只有8个字母

Live demo here。

【讨论】:

  • 首先,您的示例格式错误,因为 x,y,z 不是 constexpr。其次,这可能是真正需要 decltype 的罕见情况之一。
  • @p2rkw 它们不是 constexpr,但它们是常量表达式。
  • “编译器完成的隐式事情”示例:default+copy+move ctor, copy+move assignment-operator, ...
  • @Deduplicator:虽然隐式生成被认为是一个错误,这就是为什么即使在 C++11 中,如果指定了移动构造函数,也不会生成复制构造函数(例如)。有人谈论实际上不再自动生成复制构造函数,但它会破坏向后兼容性(C++ 非常讨厌这样做)......但是它确实表明委员会认识到这种隐式生成是一个问题 而不是解决方案。
  • @p2rkw 不,constexpr 说明符不是神奇地添加的。你误会了constexpr。 constexpr 指定实体(变量/函数)优先在编译时访问/计算,不是说变量/值是常量表达式的说明符。作为常量表达式是值的属性。将constexpr 视为编译器的提示,类似于“尝试在编译时计算它”。请注意,例如,constexpr 函数内的参数不被视为 constexpr,即使值作为常量表达式的参数传递。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-09
  • 2021-03-23
  • 2016-08-14
  • 2015-05-16
相关资源
最近更新 更多