What is decltype(0 + 0)?

我与影子孤独终老i 提交于 2020-01-11 08:05:08

问题


(Prompted by an answer.)

Given N3290, §7.1.6.2p4, where the list items are unnumbered, but numbered here for our convenience:

The type denoted by decltype(e) is defined as follows:

  1. if e is an unparenthesized id-expression or an unparenthesized class member access (5.2.5), decltype(e) is the type of the entity named by e. If there is no such entity, or if e names a set of overloaded functions, the program is ill-formed;
  2. otherwise, if e is an xvalue, decltype(e) is T&&, where T is the type of e;
  3. otherwise, if e is an lvalue, decltype(e) is T&, where T is the type of e;
  4. otherwise, decltype(e) is the type of e.

What is the type specified by decltype(0 + 0)?

Item 1 doesn't apply, 2 might, but if not, then 3 doesn't apply and 4 would be the result. So, what is an xvalue, and is 0 + 0 an xvalue?

§3.10p1:

An xvalue (an “eXpiring” value) also refers to an object, usually near the end of its lifetime (so that its resources may be moved, for example). An xvalue is the result of certain kinds of expressions involving rvalue references (8.3.2).

I don't see anything in §8.3.2 that would be helpful here, but I do know "0 + 0" doesn't involve any rvalue-references. The literal 0 is a prvalue, which is "an rvalue that is not an xvalue" (§3.10p1). I believe "0 + 0" is also a prvalue. If that's true, "decltype(0 + 0)" would be int (not int&&).

Have I missed something in my interpretation? Is this code well-formed?

decltype(0 + 0) x;  // Not initialized.

The code compiles on GCC 4.7.0 20110427 and Clang 2.9 (trunk 126116). It would not be well-formed if the decltype specified an int&& type, for example.


回答1:


From 5.19 [expr.const], every literal constant expression is a prvalue.

A literal constant expression is a prvalue core constant expression of literal type, but not pointer type. An integral constant expression is a literal constant expression of integral or unscoped enumeration type.

Therefore rule 4 applies to all literal constant expressions.




回答2:


0 + 0 is an expression of two prvalues, (n3290 par. 3.10) which applies the built-in operator+, which, per 13.6/12 is LR operator+(L,R), which is therefore a function that returns something that is not a reference. The result of the expression is therefore also a prvalue (as per 3.10).

Hence, the result of 0 + 0 is a prvalue, 0 is an int, therefore the result of 0 + 0 is an int




回答3:


It is definitely an int:

#include <iostream>
#include <typeinfo>

template<typename T>
struct ref_depth
{
        enum { value = 0 };
};

template<typename T>
struct ref_depth<T&>
{
        enum { value = 1 };
};

template<typename T>
struct ref_depth<T&&>
{
        enum { value = 2 };
};

int main() {

  std::cout
    << "int: " << typeid(int).name() << "\n"
       "decltype(0 + 0): " << typeid(decltype(0 + 0)).name() << "\n"
       "int&&: " << typeid(int&&).name() << "\n";
  std::cout 
    << "ref_depth: int: " << ref_depth<int>::value << "\n"
       "ref_depth: decltype(0 + 0): " << ref_depth<decltype(0 + 0)>::value << "\n"
       "ref_depth: int&&: " << ref_depth<int&&>::value << "\n";

}

Output:

int: i
decltype(0 + 0): i
int&&: i
ref_depth: int: 0
ref_depth: decltype(0 + 0): 0
ref_depth: int&&: 2



回答4:


Your reasoning is correct. An expression involving only constants is a constant by itself. Thus

decltype(0 + 0) x;

equals

decltype(0) x;

which equals

int x;



回答5:


GCC says int-

Code:

#include <iostream>
#include <typeinfo>

int
main ()
{
  int n;
  decltype(0 + 0) x;
  std::cout << "Type of `n': " << typeid(n).name() << std::endl;
  std::cout << "Type of `x': " << typeid(x).name() << std::endl;
}

Output:

i

i

Edit: It makes sense according to point 4, but I can't say for sure that point 2 isn't actually the one in effect. From what I can tell, 0 + 0 is evaluated to 0, and the type of 0 is int, so that is the declared type.



来源:https://stackoverflow.com/questions/5924870/what-is-decltype0-0

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!