2016-03-07 2 views
8

Рассмотрим моего простой пример ниже:Любопытно повторяющийся узор шаблона (CRTP) со статической constexpr в Clang

#include <iostream> 

template <typename T> 
class Base 
{ 
public: 
    static constexpr int y = T::x; 
}; 

class Derived : public Base<Derived> 
{ 
public: 
    static constexpr int x = 5; 
}; 


int main() 
{ 
    std::cout << Derived::y << std::endl; 
} 

В г ++, это нормально компилируется и печатает 5, как ожидался. Однако в Clang он не компилируется с ошибкой no member named 'x' in 'Derived'. Насколько я могу судить, это правильный код. Что-то не так с тем, что я делаю, а если нет, есть ли способ получить эту работу в Clang?

+0

Очень похожий вопрос: http://stackoverflow.com/q/35759047/996886 – melak47

+0

При инициализации 'y' вне' Base' класс это работает? –

+0

@ Вы не можете инициализировать 'constexpr static int' вне класса. – melak47

ответ

0

Это, вероятно, не ответ кто-то будет искать, но я решил эту проблему, добавив третий класс:

#include <iostream> 

template <typename T> 
class Base 
{ 
public: 
    static constexpr int y = T::x; 
}; 

class Data 
{ 
public: 
    static constexpr int x = 5; 
}; 

class Derived : public Base<Data>, public Data {}; 

int main() 
{ 
    std::cout << Derived::y << std::endl; 
} 

Он работает как хотелось бы, но, к сожалению, это действительно не имеет преимущества CRTP!

1

Как указано в комментариях, Initializing a static constexpr data member of the base class by using a static constexpr data member of the derived class предполагает, что поведение clang стандартно соответствует C++ 14 здесь. Начиная с Clang 3.9, ваш код успешно компилируется с -std=c++1z. Легко можно обойти, чтобы использовать функции constexpr вместо значений:

#include <iostream> 

template <typename T> 
class Base 
{ 
public: 
    static constexpr int y() {return T::x();} 
}; 

class Derived : public Base<Derived> 
{ 
public: 
    static constexpr int x() {return 5;} 
}; 

int main() 
{ 
    std::cout << Derived::y() << std::endl; 
} 
Смежные вопросы