2015-03-08 19 views
6

tôi đã biết rằng bạn có thể bật (hoặc không) phương pháp của một lớp sử dụng std::enable_ifcho phép thành viên lớp của tùy thuộc vào mẫu

cho dụ:

template<size_t D, size_t E> 
class Field 
{ 
    ... 

    size_t offset(const std::array<float,D>& p) const 
    { 
    ... 
    } 

    template<typename TT = size_t> 
    typename std::enable_if<D!=E, TT>::type 
    offset(const std::array<float,E>& p) const 
    { 
    return offset(_projection(p)); 
    } 

    ... 
}; 

này giúp việc không thể gọi là chức năng không hợp lệ trong một trường hợp cụ thể cũng như loại bỏ các lỗi quá tải ... mà, đối với tôi, là rất tốt đẹp!

Tôi muốn tiếp tục và làm cho một số thành viên của lớp học chỉ có mặt khi cần thiết. Bằng cách đó tôi sẽ nhận được một lỗi nếu tôi cố gắng sử dụng một phản đối mà sẽ có cách khác không được khởi xướng

tôi đã cố gắng để làm

template<size_t D, size_t E> 
class Field 
{ 
    ... 

    template<typename TT = projectionFunc> 
    typename std::enable_if<D!=E, TT>::type _projection; 
} 

Nhưng trình biên dịch nói với tôi:

erreur: data member ‘_projection’ cannot be a member template 

Is có cách nào để đạt được những gì tôi muốn?

+3

Bạn có thể muốn thay đổi tên từ 'offsetof' vì ai đó bao gồm trước tiêu đề của bạn và nhận macro liên quan. – chris

+0

Đó là kế hoạch, tôi chỉ đang tìm kiếm một cái tên tốt đẹp – Amxx

+0

Đó SFINAE cụ thể cũng là một chút ... icky. Trong trường hợp 'D == E' bạn kết thúc bằng' typename std :: enable_if :: type'. Một đặc điểm kiểu thư viện chuẩn là UB, do đó, có thể cho rằng việc thực hiện giả thuyết có thể gọi quy tắc "không có khả năng hợp lệ hóa có thể được tạo ra" và gọi điều này là không đúng định dạng. –

Trả lời

5

Giữ các thành viên dữ liệu trong một lớp riêng biệt mà sau đó bạn có thể chuyên khi cần.

template<size_t D, size_t E> 
class Field { 
    template<size_t, size_t> struct Field_Members { 
     int _projection; 
    }; 
    template<size_t V> struct Field_Members<V, V> { }; 
    Field_Members<D, E> m; 
}; 

và sau đó sử dụng m._projection, vv

Field_Members không phải là một lớp mẫu lồng nhau; bạn có thể di chuyển nó ra ngoài nếu muốn. Nó cũng có thể có Field kế thừa từ nó, nhưng sau đó nó sẽ là một cơ sở phụ thuộc, và bạn sẽ phải viết this->_projection, do đó, nó không tiết kiệm nhiều đánh máy.

4

AFAIK, điều này là không thể với một SFINAE đơn giản bên trong mẫu lớp học. Bạn có thể, tất nhiên, có loại thành viên phụ thuộc vào điều kiện biên dịch, tức là thông qua std::conditional, nhưng không loại trừ hoàn toàn thành viên.

gì bạn có thể làm, tất nhiên, là sử dụng một lớp mẫu, chẳng hạn như

template<bool Condition, typename T> struct Has { T value; }; 
template<typename T> struct Has<false,T> {}; 

và khai báo một thành viên (hoặc cơ sở) thuộc loại này và truy cập các đối tượng qua Has<>::value:

typename<Condition> 
class foo 
{ 
    Has<Condition, double> x; // use x.value (only if Condition==true) 
}; 
Các vấn đề liên quan