skgbanga skgbanga - 1 year ago 72
C++ Question

Final binary size: constexpr variable vs constexpr function

First, I have read this very informative answer about stylistic difference between defining a constexpr variable vs constexpr function. My question is more related with the final size of the binary when using these two. Consider this code:

// approach 1
template <typename T>
struct foo
static constexpr char name[] = "mickey";

// approach 2
template <typename T>
struct bar
static constexpr const char* getName() { return "mickey"; }

const char* func1() { return foo<int>::name; }
const char* func2() { return foo<double>::name; }

const char* func3() { return bar<int>::getName(); }
const char* func4() { return bar<double>::getName(); }

Look at this code in this godbolt link as well. While approach 1 returns different copies of name, approach 2 returns only one copy for all the different instantiations for different T. Infact, when I created 100 different types approach 2 led to a considerably smaller binary. Was wondering if anyone has experienced something similar.

Answer Source

Well, those two approaches aren't really the same. There are things you can do with foo<T>::name that you cannot do with bar<T>::getName(): I can take a pointer to it and I can take a reference to it. That ability prevents different foo<T>::names from being the same.

But with getName(), there's no such issue. You just get a prvalue - you can't take its address. The different bar<T>::getName functions themselves have to be different, but not the underlying storage.