我個人很欣賞Boost.Fusion;)
在這裏,我會用boost::fusion::map
,因爲它允許很容易地混合類型。
您需要使用標籤的類型組合(類型僅用於編譯目的)和實際類型,用來存儲數據。
讓我們來定義標籤:
class a_tag { typedef bool type; };
class b_tag { typedef int type; };
class c_tag { typedef float type; };
class d_tag { typedef double type; };
然後你就可以編寫使用Boost.Preprocessor宏這需要的標籤列表,並生成相應的boost::fusion::map
GENERATE_MY_TYPE(TypeName, (a_tag)(b_tag)(c_tag)(d_tag));
// For information: (a_tag)(b_tag)(c_tag)(d_tag) is called a sequence in PP
類型應該是這樣的:
typedef boost::fusion::map<
std::pair<a_tag, a_tag::type>,
std::pair<b_tag, b_tag::type>,
std::pair<c_tag, c_tag::type>,
std::pair<d_tag, d_tag::type>
> TypeName;
或者更有可能使用包裝boost :: fusion :: map作爲實現細節,例如:
// defined once
template <class Vector>
struct TemplateType
{
typedef Vector tags_type;
typedef detail::deduce<Vector>::type data_type
// which for Vector = boost::mpl::vector<a_tag, b_tag, c_tag, d_tag> should be
// typedef boost::fusion::map<
// std::pair<a_tag, a_tag::type>,
// std::pair<b_tag, b_tag::type>,
// std::pair<c_tag, c_tag::type>,
// std::pair<d_tag, d_tag::type>
// > data_type;
data_type m_data;
template <class T>
boost::fusion::result_of::at<T, data_type> at()
{
return boost::fusion::at<T>(m_data);
}
};
// Generated by the macro, filling boost::mpl::vector by iteration
// the sequence
typedef TemplateType< boost::mpl::vector<a_tag, b_tag, c_tag, d_tag> > TypeName;
然後,您只需要定義的類型以提供來自標記子集的轉換技巧。如果您只需要擁有完整的子集,則只能定義一次。
template <class Vector>
TypeName toTypeName(TemplateType<Vector> const& arg)
{
TypeName result;
result.fill(arg);
return result;
}
隨着填充被定義爲:
namespace detail
{
class NoAssign
{
template <class Pair, class TT> static Do(Pair const&, TTconst&) { }
};
class Assign
{
template <class Pair, class TT>
static Do(Pair& p, TTconst& tt)
{
p.second = tt.at<typename Pair::first_type>();
};
};
template <class Vector>
class Filler
{
public:
Filler(TemplateType<Vector> const& ref): m_ref(ref) {}
template <class T, class U>
void operator()(std::pair<T,U>& p) const
{
typedef typename boost::mpl::find<T,Vector>::type it;
typedef typename boost::mpl::end<Vector>::type end;
typedef typename boost::mpl::if< boost::same_type<it,end>, NoAssign, Assign> assign;
assign::Do(p, m_ref);
}
private:
TemplateType<Vector> const& m_ref;
};
}
template <class Vector>
template <class OV>
void TemplateType<Vector>::fill<OV>(TemplateType<OV> const& rhs)
{
boost::fusion::for_each(m_data, detail::Filler<OV>(rhs));
}
我愛這些問題,當然,被迫使用這兩個模板元和預設電臺預處理生成一些模板類/方法...意味着一些冗長的解決方案和一些頭痛。一旦完成,但語法可以非常簡潔(對於用戶)。
不是。這可能是一個好主意,通過這樣解釋你想要解決什麼問題。 – 2010-01-03 15:34:41
請注意,使屬性公開是一個壞主意。使他們私密,並添加setter和getters。 – 2010-01-03 15:51:08
Neil:請閱讀我的編輯以獲得解釋 – genesys 2010-01-03 15:58:04