2010-12-14 35 views
5

Có cách nào để tạo tên biến trong lớp dựa trên đối số template không?Tên biến từ đối số mẫu?

template<class T, (someconstruct) t> 

class Item { 
    public:   
     T t; 
}; 

Item<float, "Position"> myItem; 

myItem.Position = 0.123f; 

như vậy mà những gì tôi đã khởi tạo là một biến kiểu T, với định danh t (nơi t được thông qua năm bởi các lập trình viên, tức là Position, vì vậy chúng tôi có một T gọi Position? Hoặc là này kéo dài khái niệm lập trình meta mẫu hơi xa quá? p

+0

1. Không thể thực hiện được. 2. Có lẽ là một ý tưởng rất bị hỏng. 3. Tại sao bạn nghĩ rằng bạn cần điều này? (4. Bộ tiền xử lý có thể thực hiện điều này, nhưng đó không phải là câu trả lời có thể chấp nhận được) – delnan

+1

Hãy để tôi đoán: bởi vì anh ấy là lập trình viên PHP cũ ;-) –

+0

Vâng, tôi biết nó tối nghĩa! Tôi đang thực hiện một kiểu đỉnh kiểu khuôn mẫu chung, trong đó mỗi thành phần của một đỉnh có cả một loại (tức là float [3] hoặc Vector3d - và cách sử dụng, nghĩa là usage_normal, usage_position, v.v. Tôi muốn có thể tạo đỉnh bằng cách chuyển các đối số mẫu và sử dụng đệ quy mẫu để xây dựng một cấu trúc, theo cách tương tự như sau: http://www.entropygames.net/index.php?option=com_content&view=article&id=51:generic-vertices&catid=37:articles&Itemid = 56 – Robinson

Trả lời

5

Không, bạn không thể thực hiện điều này với các mẫu. Các tên biến (được gọi là "định danh") không thể được thao tác bởi các mẫu.

Bất kể điều này có vẻ như là một ý tưởng tồi. Tại sao bạn muốn để thực hiện việc này?

+0

Ok, như tôi nghi ngờ: (Cảm ơn Charles. – Robinson

6

Không, không phải với cú pháp đó, nhưng bạn có thể tạo một thiết lập tương tự với những gì bạn đang cố gắng để làm:

template < typename Field > 
struct field_value 
{ 
    typename Field::type value; 
}; 

template < typename Seq > 
struct funky_struct : boost::mpl::inherit_linearly 
    < 
    Seq 
    , boost::mpl::inherit 
    < 
     field_value< boost::mpl::placeholders::_2> 
    , boost::mpl::placeholders::_1 
    > 
    >::type 
{}; 

template < typename Field, typename Struct > 
typename Field::type & get(Struct & s) { return static_cast< field_value<Field>& >(s).value; } 

struct first_field { typedef int type; }; 
struct second_field { typedef char type; }; 

struct my_funky : funky_struct< boost::mpl::vector<first_field,second_field> > {}; 

... 
my_funky f; 
get<first_field>(f) = 23; 

tôi để lại cho phép xây dựng không mặc định cho bạn. Ngoài ra, với một số lượng nhỏ công việc này có thể được phản ánh và bạn có thể dính bất kỳ lượng thông tin hữu ích nào về các trường bên trong.

+0

+1 Tôi làm một cái gì đó tương tự trong một lớp tôi đã viết mà liệt kê các trường tin nhắn đến –

5

Điều gì đó giống như những gì bạn muốn đạt được có thể được thực hiện với kế thừa. Tức là, lớp cha có tên biến mà bạn muốn mẫu của bạn có.

struct ItemNull {}; 

template <typename X, typename Y = ItemNull> 
class Item : public X, public Y {}; 

template <typename T> struct HasPosition { T Position; }; 
template <typename T> struct HasMomentum { T Momentum; }; 

Item< HasPosition<float> > myItem1; 
myItem1.Position = 0.123f; 

Item< HasPosition<float>, HasMomentum<float> > myItem2; 
myItem2.Position = 0.1f; 
myItem2.Momentum = 0.2f; 

Đối số thứ hai tùy chọn cho phép bố cục, như minh họa trong myItem2. Để thêm một lĩnh vực thứ ba, bạn có thể thêm vào phần đuôi, hoặc mở rộng từ phía trước:

template <typename T> struct HasName { T Name; }; 

Item < 
    HasPosition<float>, 
    Item< HasMomentum<float>, HasName<std::string> > 
> myItem3; 
myItem3.Position = 0.1f; 
myItem3.Momentum = 0.2f; 
myItem3.Name = "Adam"; 

Item < 
    Item < HasPosition<float>, HasMomentum<float> >, 
    HasName<std::string> 
> myItem4; 
myItem4.Position = 0.1f; 
myItem4.Momentum = 0.2f; 
myItem4.Name = "Adam"; 

sở thích cá nhân của tôi là dành cho cựu trong hai phương pháp, bởi vì tôi thấy nó là một cách trực quan hơn để mở rộng nó vượt quá 3 lĩnh vực. Cú pháp mẫu Item có thể được đơn giản hóa bằng cách sử dụng các đối số mẫu variadic.

Mẫu Has... có thể được tạo bằng máy hoặc macro có thể được tạo để thêm trường mới một nhiệm vụ tương đối đơn giản.

#define MAKE_HAS(X) template <typename T> struct Has##X { T X; } 

MAKE_HAS(Position); 
MAKE_HAS(Momentum); 
MAKE_HAS(Name); 
Các vấn đề liên quan