Я написал шаблон класса, основанный на двух типах, которому присваивается уникальный индекс, основанный на его параметрах шаблона:
template<typename SK,typename T>
struct Component {
static uint const index;
};
Ожидается, что для каждого нового типа index
увеличивается:
Component<X,A>::index; // 0
Component<X,B>::index; // 1
Component<Y,A>::index; // 0
Component<Y,B>::index; // 1
// ...etc
Полный код, который присваивает индексы, выглядит следующим образом:
using uint = unsigned int;
template<typename SK,typename T>
struct Component
{
static uint const index;
};
template<typename SK>
class ComponentCount
{
template<typename CSK,typename CT>
friend struct Component;
private:
template<typename T>
static uint next() {
return ComponentCount<SK>::get_counter();
}
static uint get_counter()
{
static uint counter = 0;
return counter++;
}
};
Это работает, как и ожидалось, в GCC (5.1) и MSVC со следующим тестом:
// global scope
struct X {};
struct Y {};
int main()
{
// function scope
struct Z{};
uint x0 = Component<X,int>::index;
uint x1 = Component<X,double>::index;
uint x2 = Component<X,double>::index;
uint x3 = Component<X,std::string>::index;
uint x4 = Component<X,int>::index;
uint x5 = Component<X,int>::index;
std::cout << x0 << ", " << x1 << ", " << x2 << ", "
<< x3 << ", " << x4 << ", " << x5 << std::endl;
uint y0 = Component<Y,int>::index;
uint y1 = Component<Y,double>::index;
uint y2 = Component<Y,double>::index;
uint y3 = Component<Y,std::string>::index;
uint y4 = Component<Y,int>::index;
uint y5 = Component<Y,int>::index;
std::cout << y0 << ", " << y1 << ", " << y2 << ", "
<< y3 << ", " << y4 << ", " << y5 << std::endl;
uint z0 = Component<Z,int>::index;
uint z1 = Component<Z,double>::index;
uint z2 = Component<Z,double>::index;
uint z3 = Component<Z,std::string>::index;
uint z4 = Component<Z,int>::index;
uint z5 = Component<Z,int>::index;
std::cout << z0 << ", " << z1 << ", " << z2 << ", "
<< z3 << ", " << z4 << ", " << z5 << std::endl;
return 0;
}
Выходной сигнал
0, 1, 1, 2, 0, 0
0, 1, 1, 2, 0, 0
0, 1, 1, 2, 0, 0
Однако с Clang (3.6.1) выход отличается:
0, 1, 1, 2, 0, 0
0, 1, 1, 2, 0, 0
5, 2, 2, 3, 5, 5
В частности, индексы, сгенерированные для локальных типов функций (т.е. 'Z'), делают что-то странное. Как будто они увеличивают и переназначают индекс каждый раз, когда вызывается Component<Z,...>
.
Почему это происходит? Это ошибка компилятора? Существуют ли какие-либо особые соображения при использовании функциональных локальных типов с шаблонами (post С++ 11)?
Полный пример можно найти здесь: http://coliru.stacked-crooked.com/a/7fcb989ae6eab476
== Правка ==
Я решил опубликовать эту проблему для clang bugtracker, поэтому, если кто-то еще сталкивается с этим: