2010-02-19 103 views
5

是否可以写一个类:可能将名称作为参数传递给C++模板?

template<typename T, ... name> struct Magic { 
    T name; 
}; 

这样的:

Magic<int, foo> gives: 

Magic<int, foo> { 
    int foo; 
} 

Magic<float, bar> gives: 

Magic<float, bar> { 
    float bar; 
} 

基本上,我希望能够指定不仅类型,但也是成员变量的名称。

+0

模板处理类型。他们可以引用的唯一名称是类型名称,而不是词汇名称。预处理器用于词汇名称。 – GManNickG 2010-02-19 00:45:08

+0

我能想到的唯一方法就是使用继承+ crtp模式,比如'struct bar_variable {float bar; }; struct Magic :named_variable {}; Magic ;' – Anycorn 2010-02-19 00:46:21

回答

5

这是不可能的,你不得不求助于基于宏的解决方案或使用预定义的一组提供指定成员的类型。

一种可能的基于宏的方法:

#define MAGIC(name_) \ 
    template<typename T> struct Magic1 { \ 
     T name_; \ 
    }; 

MAGIC(foo); 

或:

#define MAGIC(type_, name_) \ 
    struct Magic1 { \ 
     type_ name_; \ 
    }; 

MAGIC(foo); 

使用预处理器魔法,例如利用Boost.Preprocessor,您应该能够以更便利的方式生成名为成员的n

另一种方法可以是使用预定义的从提供一定的命名成员的类,你继承:

enum { MemberNameFoo, MemberNameBar }; 

template<class T, int id> 
struct named_member; 

template<class T> 
struct named_member<T, MemberNameFoo> { 
    T foo; 
}; 

template<class T> 
struct named_member<T, MemberNameBar> { 
    T bar; 
}; 

// holder for the above, just one member for this example: 

template<class T, int name> 
struct holder : named_member<T, name> {}; 

// using it: 

typedef holder<int, MemberNameFoo> HasFoo; 
typedef holder<int, MemberNameBar> HasBar; 

使用编译时间列表,那么你可以从ňnamed_member实例继承,Boost.MPL可以帮助这里。

+0

如果您实际上并不太在意您的成员的名字是什么,您可以使用类型列表或C++ 0x可变参数模板来做到这一点。我已经完成它来实现编写自己的序列化和反序列化方法的类。 – Omnifarious 2010-02-19 01:46:33

+0

但问题是关于它的*“可能将名称[*]”*传递给模板,而不是如何为某些任意命名的类型集合生成持有者。 – 2010-02-19 02:06:28

+0

@gf,这是真的。虽然人们常常不问这个问题的确切含义。他们有一个解决问题的解决方案,并询问如何使解决方案工作,而不是如何解决实际问题。:-) – Omnifarious 2010-02-19 04:09:18

1

不,这是不可能的。有一种叫做typelist的构造,可以用来实现你喜欢的效果。不幸的是,即使那样你也不会得到有名的成员,你将得到访问器函数,其名称如MyClass::getField<1>()

在C++ 0x中,你可以比带有variadic templates的类型列表更好。但是你仍然可以使用看起来就像C++一样的存取函数。

在这里放下一个可变模板的例子是很诱人的,因为它不会太大。不幸的是,我认为如果做得好,我需要花几个小时的时间来研究可变参数模板是如何工作的。我可以相对容易地做一个愚蠢的版本,但我希望这个愚蠢的版本会比以前的版本好多少。

相关问题