2

I'm wondering what happen internally when I define a constexpr variable inside a function. Is the program storing each version of the called function's constexpr variables ?

Example:

template <class T, std::size_t M, std::size_t N>
template <std::size_t M2, std::size_t N2>
Matrix<T, M, N>::Matrix(const Matrix<T, M2, N2>& m)
{
    constexpr T m_min(MATHS::min(M, M2));
    constexpr T n_min(MATHS::min(N, N2));
    std::size_t i(0), j(0);
    for ( ; i < m_min ; ++i )
    {
        for ( j = 0 ; j < n_min ; ++j )
            m_elts[i][j] = m.m_elts[i][j];
        for ( ; j < N ; ++j )
            m_elts[i][j] = MATHS::CST<T>::ZERO;
    }
    for ( ; i < M ; ++i )
    {
        for ( j = 0 ; j < N ; ++j )
            m_elts[i][j] = MATHS::CST<T>::ZERO;
    }
}

//m_elts is : std::array<std::array<T, N>, M> m_elts;
Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
Cevik
  • 313
  • 1
  • 4
  • 17
  • It depends. It might be necessary to create unique addresses for each constexpr object. It has even been possible at some point to define a constexpr struct with a mutable data member, but I think there's a defect report against such things. – dyp Jul 28 '15 at 20:53
  • Provide specific examples of the code to get better answers. as @dyp says it depends on how the constexpr variable is defined and used. – Speed8ump Jul 28 '15 at 21:11
  • Nice follow up, I wish I had a nice answer for you. – Niall Jul 28 '15 at 21:18
  • This question: [Understanding the example on lvalue-to-rvalue conversion](http://stackoverflow.com/q/28506342/1708801) is kind of an extreme example but gives a good cases where the results somewhat unexpected. – Shafik Yaghmour Jul 29 '15 at 13:07
  • I retracted my close vote since the example makes the question clear, although I still think a MCVE would be better. – Shafik Yaghmour Jul 30 '15 at 20:59
  • Somewhat related: [When and why would you use static with constexpr?](http://stackoverflow.com/q/26152096/) – dyp Jul 30 '15 at 21:00

1 Answers1

7

This is going to depend on the optimizer and the example but in general I am going to say that if the variable is not ODR-used(loosely either a variables address is taken or it is bound to a reference) then it is likely the compiler will not need to store the value someplace during run-time.

Given the following contrived example loosely similar to the one you provided:

#include <cstdio>
#include <algorithm>

template <typename T, size_t M, size_t N>
void func1( int x1, int x2, int x3 )
{
  constexpr T y1 = std::min(M,N) ;
  int y2 = x2 ;
  int z1 = x1 + y1 ;
  int z2 = x3 + y2 ;

  printf( "%d %d %d\n", x1, z1, z2 ) ;
}

template <typename T, size_t M, size_t N>
void func2( int x1, int x2, int x3 )
{
  constexpr int y1 = std::min(M,N) ;
  int y2 = x2 ;
  int z1 = x1 + y1 ;
  int z2 = x3 + y2 ;

  const int *p1 = &y1 ;

  printf( "%d %d %d %p\n", x1, z1, z2, p1 ) ;
}

int main()
{
  int x = 1, y = 2, z = 3 ;
  func1<int,10,20>( x, y, z ) ;
  func2<int,10,20>( x, y, z ) ;
}

we can see using a godbolt live example, we can see that in func1 the constexpr variable y1 is replaced with a literal:

leal     10(%rdi), %edx #, z1

It is not odr-used since we don't take it's address nor bind a reference to it but in func2 we do indeed take it's address and use it and so it is required to exist at runtime:

movl    $10, 12(%rsp)   #, y1
Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
  • Ok, i didn't know the ODR aspect of things. A simple referencing instruction involving a static helper variable as an identity matrix can radically change the behavior of a program ! – Cevik Jul 30 '15 at 21:31