Question: ```
#include <iostream>
using namespace std;

template<typename T> void print(T&& mX) 
{
    std::cout << std::forward<T>(mX) << std::endl;  
}

struct SomeStruct
{
    static constexpr const char* someString{"hello!"};
    SomeStruct()
    {
        print(someString);
    }
};

int main() 
{
    SomeStruct s{};
    return 0;
}

```

---

`clang++ -std=c++1y ./code.cpp -o code.o`

> 
> /tmp/code-a049fe.o: In function `SomeStruct::SomeStruct()':
>  ./code.cpp:(.text.\_ZN10SomeStructC2Ev[\_ZN10SomeStructC2Ev]+0xa):
>  undefined reference to `SomeStruct::someString' clang: error: linker
>  command failed with exit code 1 (use -v to see invocation)
> 
> 
> 

---

`g++ -std=c++1y ./code.cpp -o code.o`

> 
> /tmp/ccyrTsjS.o: In function `SomeStruct::SomeStruct()':
>  code.cpp:(.text.\_ZN10SomeStructC2Ev[\_ZN10SomeStructC5Ev]+0xd):
>  undefined reference to `SomeStruct::someString' collect2: error: ld
>  returned 1 exit status
> 
> 
> 

---

Why is this linker error happening? Isn't `someString` supposed to be resolvable at compile-time?

Also, the error doesn't happen if `print(someString)` is replaced with `cout << someString;`

Answer: 
Because you are taking a reference the variable is odr-used and this requires a definition out of line:

```
constexpr const char* SomeStruct::someString;

```

[see it working live](http://coliru.stacked-crooked.com/a/ecd786eb2f72b231).

From the draft C++14 standard section `3.2` *[basic.def.odr]*:

> 
> A variable x whose name appears as a potentially-evaluated expression ex is odr-used by ex unless applying
>  the lvalue-to-rvalue conversion (4.1) to x yields a constant expression (5.20) that does not invoke any nontrivial
>  functions and, if x is an object, ex is an element of the set of potential results of an expression e,
>  where either the lvalue-to-rvalue conversion (4.1) is applied to e, or e is a discarded-value expression [...]
> 
> 
> 

For example the following alternative `print` would not odr-use `someString`:

```
template<typename T> void print(T mX) 
{
    std::cout << mX << std::endl;  
}

```
There are a narrow set of circumstances under which you may not bother to define a `static` data member (whether it's `constexpr` or not, and whether it takes advantage of this initialisation form or not), and this is not one of them, because you indirectly take the address of it (and therefore it must exist as an actual object in memory).

You can kind of think of it as a static data member that can't simply be "inlined" at the point of its use, due to *what* that use is.

Define `someString`.