I have noticed a strange behavior when trying to compile the code included below. I have 4 files as follows
createshared.h:
#ifndef CREATESHARED_H_
#define CREATESHARED_H_
#include <memory>
#include <utility>
#ifdef USE_REFREF
template<typename T, typename... Args>
std::shared_ptr<T> create_shared(Args&&... args)
{
class HelperClass : public T
{
public:
HelperClass (Args&& ... nargs) : T(std::forward<Args...>(nargs)...) {}
virtual ~HelperClass() = default;
};
return std::make_shared<HelperClass>(std::forward<Args...>(args)...);
}
#else
template<typename T, typename... Args>
std::shared_ptr<T> create_shared(Args... args)
{
class HelperClass : public T
{
public:
HelperClass (Args ... nargs) : T(nargs...) {}
virtual ~HelperClass() = default;
};
return std::make_shared<HelperClass>(args...);
}
#endif
#endif
staticinitclass.h
#ifndef STATICINITCLASS_H_
#define STATICINITCLASS_H_
class StaticInitClass
{
public:
#ifdef INITIALIZE_IN_HEADER
static const int default_i = 1;
#else
static const int default_i;
#endif
virtual ~StaticInitClass() = default;
StaticInitClass() = delete;
protected:
StaticInitClass(int i);
};
#endif
staticinitclass.cpp:
#include "staticinitclass.h"
#include <iostream>
#ifndef INITIALIZE_IN_HEADER
const int StaticInitClass::default_i = 2;
#endif
StaticInitClass::StaticInitClass(int i)
{
std::cout << "Created with " << i << std::endl;
}
main.cpp:
#include "staticinitclass.h"
#include "createshared.h"
#include <memory>
int main(int argc, const char* argv[])
{
auto shared = create_shared<StaticInitClass>(StaticInitClass::default_i);
}
With no flags, the program compiles and runs fine.
$ g++ -std=c++11 main.cpp staticinitclass.cpp
$ ./a.out
Created with 2
Fine, because default_i is an integral type, we can initialize it in the header. Let's do that
$ g++ -std=c++11 main.cpp staticinitclass.cpp -DINITIALIZE_IN_HEADER
$ ./a.out
Created with 1
Good, still compiles and works fine. Now, let's add our && and std::forward
$ g++ -std=c++11 main.cpp staticinitclass.cpp -DINITIALIZE_IN_HEADER -DUSE_REFREF
/tmp/cc3G4tjc.o: In function `main':
main.cpp:(.text+0xaf): undefined reference to `StaticInitClass::default_i'
collect2: error: ld returned 1 exit status
Linker error. Well, let's now try initializing our default_i member in the .cpp
$ g++ -std=c++11 main.cpp staticinitclass.cpp -DUSE_REFREF
$ ./a.out
Created with 2
And it works again. Using clang yields the same result, which would lead me to believe that this isn't just an isolated compiler error, but perhaps something in the language itself that prevents the static initialization. I just can't seem to connect why adding && would cause the break.
Currently I am using g++ 4.8.2 and clang++ 3.5 on Ubuntu 14.04
Any ideas what is broken here when using -DINITIALIZE_IN_HEADER and -DUSE_REFREF?