Thread: constexpr and auto references

  1. #1
    Registered User
    Join Date
    May 2012
    Location
    Brazil
    Posts
    58

    constexpr and auto references

    I have some doubts about constexpr and auto when applied to references.

    From what I've read, constexpr imposes top-level const. In that case, what's the effect of doing:
    Code:
    constexpr int &ref = i; // i is a global non-const variable
    This doesn't make sense to me as we can't have a const reference (only a reference to const).

    Likewise, with auto:
    Code:
    const int i = 10;
    // ok; auto retains the low-level const and ref is a reference to a const int
    auto &ref = i;
    
    auto &ref2 = 10; // error; the low-level const cannot be inferred here
    const auto &ref3 = 10; // ok, adding top-level const fixes it
    Why `const auto` here has a different meaning than when declaring any other type?
    Is there an explanation for this cases or this is just the way it is and those use of auto and constexpr with references are an exception?

    Thanks in advance.

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Hmm... the rule is:
    Quote Originally Posted by C++11 Clause 7.1.5 Paragraph 9
    A constexpr specifier used in an object declaration declares the object as const. Such an object shall have literal type and shall be initialized. If it is initialized by a constructor call, that call shall be a constant expression (5.19). Otherwise, or if a constexpr specifier is used in a reference declaration, every full-expression that appears in its initializer shall be a constant expression. Each implicit conversion used in converting the initializer expressions and each constructor call used for the initialization shall be one of those allowed in a constant expression (5.19).
    It seems to me therefore that your example should not compile since i is not a constant expression. However, it does compile for me when I tested with g++ 4.8.2, though curiously the compiler rejects the declaration when i is local. Perhaps this is a compiler bug.

    As for its usage: I am not familiar with constexpr used in a reference declaration. My guess would be that it is allowed for completeness of syntax.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User
    Join Date
    May 2012
    Location
    Brazil
    Posts
    58
    Quote Originally Posted by laserlight
    It seems to me therefore that your example should not compile since i is not a constant expression. However, it does compile for me when I tested with g++ 4.8.2, though curiously the compiler rejects the declaration when i is local. Perhaps this is a compiler bug.
    Thanks laserlight.
    I did check the standard, but it didn't help much concerning the constexpr doubt. But I'm afraid that's not a bug; I'm reading C++ Primer and it says that one can bind references declared as constexpr to variables that have a fixed address, hence my use of a global variable. Making it static works too (clang 6.0).

    Quote Originally Posted by laserlight
    As for its usage: I am not familiar with constexpr used in a reference declaration. My guess would be that it is allowed for completeness of syntax.
    Yes, I was wondering whether that behavior had any logical sense. This would satisfy my curiosity then.
    Last edited by koplersky; 02-08-2015 at 01:50 PM.

  4. #4
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    From what I've read, constexpr imposes top-level const.
    O_o

    Nope.

    The `constexpr' attribute only informs about an expression that can be rigidly evaluated by the compiler during the compilation of a translation unit. A `constexpr' isn't then simply an expression which is qualified by the `const' attribute. (In fact, a `constexpr' doesn't have to even have to be an expression where the `const' attribute is valid.) A compiler is only allowed to evaluate certain kinds of expressions. (As you may imagine, throwing the `constexpr' attribute at an expression doesn't magically coerce the expression into one which the compiler may evaluate.) The `constexpr' attribute doesn't really impose a restriction. The `constexpr' attribute more states that the expression should conform to the requirements which allows more meaningful messages.

    It seems to me therefore that your example should not compile since i is not a constant expression.
    You are going to love this stuff!

    The `i' expression in the first example of the first post is actually a constant expression.

    We are not looking at the value for the `i' variable; we are looking at the address of the `i' variable because we are only forming a reference.

    Code:
    int i;
    constexpr int &ref = i; // fine
    constexpr int ref = i; // wrong
    Yes, I was wondering whether that behavior had any logical sense. This would satisfy my curiosity then.
    The utility of binding a reference in a `constexpr' isn't for feature parity or completeness of syntax.

    You couldn't make as many useful, if elaborate, decisions if a reference wasn't a `constexpr' evaluation.

    Soma

    Code:
    #include <cstdlib>
    #include <iostream>
    
    const int gC(0);
    int gM(0);
    constexpr const int & gRC(gC);
    constexpr int & gRM(gM);
    
    const int & GetCB(){return(gC);}
    constexpr const int & GetCG(){return(gC);}
    const int & GetMB(){return(gM);}
    constexpr const int & GetMG(){return(gM);}
    
    /**************************************************************/
    
    template
    <
        int F
    >
    struct SV
    {
        static const int R = F;
    };
    
    /**************************************************************/
    
    const int gVariant1T(1);
    const int gVariant1F(2);
    
    constexpr const int & Choose1
    (
        bool fWhich
    )
    {
        return(fWhich ? (gVariant1T) : (gVariant1F));
    }
    
    constexpr const int & gV1T(Choose1(true));
    constexpr const int & gV1F(Choose1(false));
    
    /**************************************************************/
    
    const int gVariant2T(1);
    const int gVariant2F(2);
    
    const int & Choose2()
    {
        return((rand() % 2) ? (gVariant1T) : (gVariant1F));
    }
    
    const int & gV2T(Choose2());
    const int & gV2F(Choose2());
    
    /**************************************************************/
    
    int main()
    {
        gRM = 0; // `gRM' is indeed a reference to a mutable value
        SV<gC> s0;
        //SV<gM> s1;
        SV<gRC> s2;
        //SV<gRM> s3;
        //SV<GetCB()> s4;
        SV<GetCG()> s5;
        //SV<GetMB()> s6;
        //SV<GetMG()> s7;
        std::cout << SV<gV1T>::R << '\n';
        std::cout << SV<gV1F>::R << '\n';
        //std::cout << SV<gV2T>::R << '\n';
        //std::cout << SV<gV2F>::R << '\n';
        std::cout << gV2T << '\n';
        std::cout << gV2F << '\n';
        return(0);
    }
    “Salem Was Wrong!” -- Pedant Necromancer
    “Four isn't random!” -- Gibbering Mouther

  5. #5
    Registered User
    Join Date
    May 2012
    Location
    Brazil
    Posts
    58
    Quote Originally Posted by phantomotap
    You couldn't make as many useful, if elaborate, decisions if a reference wasn't a `constexpr' evaluation.
    Great, thanks Soma. I was failing to see how constexpr references could be different.

    As for the auto, I had it the other way around anyway, so problem solved.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 1
    Last Post: 11-06-2014, 01:33 PM
  2. Constexpr and generalized constant expressions in C++11
    By webmaster in forum C++ Programming
    Replies: 8
    Last Post: 09-29-2011, 06:37 PM
  3. DLL References
    By Govtcheez in forum Tech Board
    Replies: 7
    Last Post: 01-11-2005, 02:56 AM
  4. declare references to references works!
    By ManuelH in forum C++ Programming
    Replies: 4
    Last Post: 01-20-2003, 08:14 AM