當我嘗試編譯下面包含的代碼時,我注意到了一個奇怪的行爲。我有4個文件如下編譯器錯誤或正確的行爲爲靜態const成員變量,variadic模板和&&?
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);
}
沒有標誌,程序編譯並運行正常。
$ g++ -std=c++11 main.cpp staticinitclass.cpp
$ ./a.out
Created with 2
精細,因爲default_i是不可或缺的類型,我們可以在頭初始化。讓我們做到這一點
$ g++ -std=c++11 main.cpp staticinitclass.cpp -DINITIALIZE_IN_HEADER
$ ./a.out
Created with 1
好,還是編譯並運行良好。現在,讓我們添加& &和std ::向前
$ 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
連接錯誤。好了,現在讓我們來嘗試初始化我們default_i成員在.cpp
$ g++ -std=c++11 main.cpp staticinitclass.cpp -DUSE_REFREF
$ ./a.out
Created with 2
它再次工作。使用clang會得到相同的結果,這會導致我相信這不僅僅是一個孤立的編譯器錯誤,而可能是語言本身阻止靜態初始化的一些東西。我似乎無法連接爲什麼加入& &會導致休息。
目前我使用在Ubuntu 14.04
任何想法G ++ 4.8.2和鐺++ 3.5使用-DINITIALIZE_IN_HEADER和-DUSE_REFREF當這到底是怎麼壞了?
爲靜態數據成員提供初始化並不意味着您也提供了一個定義。當你結合兩個'-D'選項時,你最終會使用這個靜態成員的odr,因此需要爲它提供一個定義。 – Praetorian 2014-12-02 20:46:25