2016-03-07 13 views
8

Hãy xem xét ví dụ đơn giản của tôi dưới đây:Tò mò lặp đi lặp lại mô hình mẫu (CRTP) với constexpr tĩnh trong 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; 
} 

Trong g ++, này biên dịch tốt và in 5 như mong đợi. Trong Clang, tuy nhiên, nó không biên dịch với lỗi no member named 'x' in 'Derived'. Theo như tôi có thể nói đây là mã chính xác. Có điều gì đó sai trái với những gì tôi đang làm, và nếu không, liệu có cách nào để có công việc này trong Clang?

+0

câu hỏi Rất tương tự: http://stackoverflow.com/q/35759047/996886 – melak47

+0

Nếu bạn khởi tạo 'y' bên ngoài của 'Base' lớp nó hoạt động? –

+0

@Ben bạn không thể intialize một 'constexpr static int' bên ngoài lớp. – melak47

Trả lời

0

Điều này có lẽ không phải là câu trả lời bất cứ ai có thể tìm kiếm, nhưng tôi giải quyết vấn đề bằng cách thêm một lớp thứ ba:

#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; 
} 

Nó hoạt động như mong muốn, nhưng tiếc là nó không thực sự có những lợi ích của CRTP!

1

Khi được liên kết trong nhận xét, Initializing a static constexpr data member of the base class by using a static constexpr data member of the derived class cho thấy hành vi kêu vang là tuân thủ tiêu chuẩn tối đa C++ 14 tại đây. Bắt đầu với Clang 3.9, mã của bạn biên dịch thành công với -std=c++1z. Một workaround dễ dàng có thể là sử dụng chức năng constexpr thay vì giá trị:

#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; 
} 
Các vấn đề liên quan