Is declval() the same as (*(T*)nullptr)?

后端 未结 2 692
温柔的废话
温柔的废话 2020-12-29 22:47

Is declval() just a replacement for the old trick of (*(T*)NULL) to get an instance of T in a decltype without needing to worry about T\'s

相关标签:
2条回答
  • 2020-12-29 23:32

    declval() has the advantage that if it is used in an evaluated context (i.e., odr-used) then the program is ill-formed (20.2.4p2), and a diagnostic is required to be issued (per 1.4p1). Typically this is enforced through a static_assert in the library:

    c++/4.7/type_traits: In instantiation of '[...] std::declval() [...]':
    source.cpp:3:22:   required from here
    c++/4.7/type_traits:1776:7: error: static assertion failed: declval() must not be used!
    

    declval also works on reference types:

    using S = int &;
    using T = decltype(std::declval<S>());
    using U = decltype(*(S *)nullptr);  // fails
    

    Where the type is not a reference type, declval will give an rvalue type where nullptr gives an lvalue.

    0 讨论(0)
  • 2020-12-29 23:35

    No, declval<T>() is not the same as (*(T*)nullptr). And decltype(expr.bar) is not the same as decltype((expr.bar)).

    The former comparison compares expressions. The latter use of decltype inspects the expression and the former use of decltype inspects the declared type of expr.bar. So you have to paren your uses of the decltype operand to make a useful comparison of the types and you will find they are different.

    struct A {};
    
    struct B {
        A a;
    };
    
    // E1: B().a 
    // E2: declval<A>().a
    // E3: (*(B*)0).a
    // E4: ((B&&)(*(B*)0)).a
    

    In these 4 expressions, all expressions have type A. E1 is a prvalue (in C++14 it is an xvalue. Some compilers probably will treat it as an xvalue even in their C++11 mode), E2 is an xvalue. E3 is an lvalue and E4 is an xvalue again.

    // T1: decltype((*(B*)0).a)
    // T2: decltype(((*(B*)0).a))
    

    In these two types, the first decltype gives the type of the member named by the expression. The member has type A, so T1 is A. The second decltype yields the type of the expression, modified by & if the expression is an lvalue and modified by && if the expression is an xvalue. The expression is an lvalue, so T2 is A&.

    0 讨论(0)
提交回复
热议问题