2012-04-13 34 views
7

Với mẫu này:Sử dụng enable_if để tùy thêm một thành viên struct

template <class A> 
struct Something { 
    ... // members common to all template instantiations for all A types 
    SpecialType member; // but not this - I want this to be conditional... 
} 

... Tôi muốn sử dụng "enable_if" để có thành viên SpecialType tồn tại có điều kiện; nghĩa là, chỉ khi mẫu được khởi tạo với kiểu A = SpecialCase1 hoặc SpecialCase2. Trong tất cả các trường hợp khác, tôi muốn thành viên SpecialType bị thiếu.

Trong trường hợp bạn tự hỏi tại sao, đây là về tối ưu hóa - nghĩa là không mang tải trọng vô ích trong cấu trúc. Tôi là một newbie trong metaprogramming mẫu, nhưng tôi hiểu tôi cần "enable_if" và hai "is_same" bằng cách nào đó - không chắc chắn chính xác như thế nào, mặc dù ...

EDIT: Làm điều đó với chung C++ (tức là không có đặc hiệu tăng cường) sẽ là một lợi thế.

Trả lời

5

Vâng: sử dụng lớp cơ sở.

struct Empty {}; 

struct SpecialTypeCnt { SpecialType member; }; 

template <typename A> 
struct Something: if_< /* cond */ , SpecialTypeCnt, Empty>::type { 
}; 

đâu if_ được định nghĩa là:

template <typename, typename, typename E> struct if_ { typedef E type; }; 

template <typename T, typename E> 
struct if_<std::true_type, T, E> { typedef T type; }; 

(Bạn cũng có thể chuyên về một boolean)

Bây giờ tất nhiên, bạn cần phải thể hiện tình trạng của bạn đúng cách.


Có nói rằng, bạn có lẽ không nên sử dụng chỉ struct. Thay vào đó, bạn nên sử dụng class để cung cấp các hoạt động cần được áp dụng trên member. Sau đó, bạn cung cấp class Null với hành vi mặc định và class SomeType với hành vi cụ thể là member.

Nếu không, bạn sẽ ghi lại điều kiện ở mọi nơi bạn cần "có thể" sửa đổi member và điều đó gây phiền toái thực sự nhanh chóng.

+2

'if_' thường được gọi là' std :: conditional'. –

+0

@KerrekSB: Ah cảm ơn, tôi là một phần của một bộ đếm thời gian cũ tôi sợ. Trong Boost MPL, nó là 'if_' :) Tôi chưa đào sâu trong thư viện mới của C++ 11:/ –

5

Bạn không cần enable_if cho việc này. Chuyên cấu trúc của bạn cho các trường hợp đặc biệt và để triển khai mặc định cho phần còn lại:

template <class A> 
struct Something 
{ 
    // your default implementation 
}; 

template <> 
struct Something<SpecialCase1> 
{ 
    // your SpecialCase1 implementation 
}; 

template <> 
struct Something<SpecialCase2> 
{ 
    // your SpecialCase2 implementation 
}; 
+0

Đó sẽ gây ra lại kiến nghị của tất cả các lĩnh vực chung và chức năng thành viên - Tôi muốn tránh điều này (DRY). – ttsiodras

+0

@ttsiodras - sử dụng thành phần hoặc kế thừa và làm những gì tôi đề xuất trên một thành viên hoặc một lớp cơ sở – bobah

2

Để không lặp lại các thành viên chung:

Xác định lớp BaseSomething:

template <class A> 
     struct BaseSomething { 
      ... // members common to all template instantiations for all A types 
       }; 

Xác định lớp SpecialSomething:

template <class A> 
      struct SpecialSomething { 
       SpecialType member; 
       ...//SpetialType related functionality 
        }; 

Xác định lớp Something:

template <class A> 
      struct Something :public BaseSomething<A>{ 

        }; 



    template<> 
    struct Something<SpecialCase1>:public BaseSomething<A>{ 
        SpecialSomething<SpecialCase1> special; 
         }; 


template<> 
struct Something<SpecialCase2>:public BaseSomething<A>{ 
       SpecialSomething<SpecialCase2> special; 
        }; 
+0

Đó là thư viện gần nhất với những gì tôi cần - nhưng chắc chắn điều này dài hơn nhiều so với một dòng duy nhất "enable_if" ... – ttsiodras

+2

Nếu tiết không hoạt động cho bạn thì bạn nên ít nhất có một cái nhìn khó khăn về sự lựa chọn của bạn bằng cách sử dụng ngôn ngữ C++.Nó có thể rất tiết tấu vào những thời điểm. –

Các vấn đề liên quan