2013-08-23 68 views
6

Tôi có một lớp trong không gian tên trong tệp tiêu đề. Lớp này yêu cầu một kiểu mẫu và tôi chỉ muốn sử dụng một số loại nhất định. Dưới đây cho thấy một ví dụ.Lớp riêng tư trong không gian tên

file a.hpp

// a.hpp 
namespace a_ns { 
template<class T>  
class a { 
    // stuff 
}; 
typedef a<double> a_double; 
} // end of namespace 
// stuff 

file b.hpp

// b.hpp 
#include <a.hpp> 
namespace b_ns { 
    typedef a_ns::a_double b; 
} 

file main.cpp

// main.cpp 
#include "b.hpp" 
int main() { 
    b_ns::b my_b; // <<<--- I LIKE this! 
    a_ns::a<float> my_a_which_is_not_allowed; // <<<--- I DO NOT LIKE THIS THOUGH! D: 
} 

Như bạn có thể nhìn thấy từ khá mong ra dụ, mục tiêu cuối cùng là KHÔNG PHÉP người dùng cuối tuyên bố class a với float làm tên tệp, d chỉ có thể sử dụng các lớp được xác định trước với các loại cụ thể, như được khai báo bởi typedef a<double> a_double;.

Tôi nghĩ ví dụ trên sẽ cho phép điều này, tuy nhiên tôi đã sai, vì tôi có thể tạo a<float> như trên, vì tôi bao gồm b.hpp, bao gồm a.hpp! Vì vậy, bạn thấy vấn đề! (hy vọng?)

Có lẽ có một giải pháp đơn giản, nếu điều này là có thể.

Trả lời

7

Nếu bạn chỉ muốn để có thể sử dụng các bí danh loại và không sử dụng a trực tiếp, bạn có thể đặt nó vào một namespace thực hiện mà người dùng nên biết không sử dụng:

namespace a_ns { 

namespace detail { 
    template<class T>   
    class a { 
     // stuff 
    }; 
} 

typedef detail::a<double> a_double; 
} // end of namespace 

Bây giờ bất cứ điều gì có thể sử dụng a_double, nhưng để sử dụng trực tiếp a, không gian tên detail của bạn sẽ phải được đào sâu vào và thường được chấp nhận là điều xấu. Nếu người dùng quyết định họ muốn làm điều đó, họ đã từ bỏ việc tránh rắc rối và bạn không nên thực hiện các biện pháp bổ sung để ngăn họ tự làm tổn thương bản thân họ.

+1

Thực ra tôi thích điều này - Tôi e rằng không có cách nào để đánh bại các lập trình viên gây rắc rối. –

+0

@ DieterLücking, Một khi bạn vượt qua thực tế là họ phải cố tình đào sâu vào lỗ, bạn bắt đầu lo lắng ít hơn nhiều về việc ngăn chặn nó. Nếu họ muốn tự lừa mình, hãy để họ. Nếu có gì đó trong đó có thể thực sự giúp họ, ít nhất là bây giờ họ không cần một hack để có được nó. – chris

+0

hoặc như Herb Sutter đặt nó: bảo vệ chống lại Murphy, không Machiavelli – TemplateRex

0

Đây là cách bạn có thể sử dụng một static_assert

#include <type_traits> 
template <typename T> 
class X 
{ 
    T i; 
    static_assert(!std::is_same<float,T>::value,"Don't use floating point"); 
}; 



int main() 
{ 
    X<int> a; 
    //X<float> b; fails at compile time 
    return 0; 
} 

này sẽ làm việc càng lâu càng biến không phải là const hoặc dễ bay hơi