当我尝试为通用容器(例如std::list<...>
)而不是特定的容器(例如std::list<double>
)专门化模板变量时,我收到gcc 5.3
的链接错误(但不是与clang 3.5
)
/tmp/ccvxFv3R.s: Assembler messages:
/tmp/ccvxFv3R.s:206: Error: symbol `_ZL9separator' is already defined
http://coliru.stacked-crooked.com/a/38f68c782d385bac
#include<string>
#include<iostream>
#include<list>
#include<forward_list>
#include<vector>
template<typename T> std::string const separator = ", ";
template<typename... Ts> std::string const separator<std::list<Ts...> > = "<->";
template<typename... Ts> std::string const separator<std::forward_list<Ts...>> = "->";
int main(){
std::cout << separator<std::vector<double>> << '\n';
std::cout << separator<std::list<double>> << '\n';
std::cout << separator<std::forward_list<double>> << '\n';
}
(这可以很好地编译clang 3.5
并按预期工作。此外,可变参数模板不是导致问题的原因,我尝试使用非可变参数模板。)
如果这不是gcc
中的错误,您认为是否有解决方法?我试图使用类专门化,但也不可能:
template<class T>
struct separator{
static std::string const value;
};
template<class T>
std::string const separator<T>::value = ", ";
template<typename... Ts>
std::string const separator<std::list<Ts...>>::value = "<->";
template<typename... Ts>
std::string const sep<std::forward_list<Ts...>>::value = "->";
答案 0 :(得分:1)
这似乎是gcc
的问题。解决方法(使用类模板),如@ T.C.建议。
template<class T>
struct sep{
static const std::string value;
};
template<class T>
const std::string sep<T>::value = ", ";
template<typename... Ts>
struct sep<std::list<Ts...>>{
static const std::string value;
};
template<typename... Ts>
const std::string sep<std::list<Ts...>>::value = "<->";
template<typename... Ts>
struct sep<std::forward_list<Ts...>>{
static const std::string value;
};
template<typename... Ts>
const std::string sep<std::forward_list<Ts...>>::value = "->";
以后是模板变量(所以具有相同的接口)
template<typename T> std::string const separator = sep<T>::value;
这适用于gcc
和clang
。
或@ T.C。建议使用静态函数成员而不是静态成员(代码少)
template<class T>
struct sep{
static std::string value(){return ", ";}
};
template<typename... Ts>
struct sep<std::list<Ts...>>{
static std::string value(){return "<->";}
};
template<typename... Ts>
struct sep<std::forward_list<Ts...>>{
static std::string value(){return "->";}
};
...
template<typename T> std::string const separator = sep<T>::value();
或使用constexpr const char*
template<class T>
struct sep{static constexpr const char* value = ", ";};
template<typename... Ts>
struct sep<std::list<Ts...>>{static constexpr const char* value = "<->";};
template<typename... Ts>
struct sep<std::forward_list<Ts...>>{static constexpr const char* value = "->";};
...
template<typename T> std::string const separator = sep<T>::value;
我尝试使用const_str
(constexpr
友好版本的std::string
)但我收到了奇怪的链接器错误。