解決方案1:基於SFINAE的技術
該解決方案是基於一個事實,即沒有一個模板的實例化過程中替換模板參數並不會導致編譯錯誤(換人失敗不是一種錯誤):代替,該模板簡單地忽略過載解析度。因此,通過一些技巧,您可以根據實例化時提供的模板參數來選擇某個函數模板的哪些重載應該可見。
當使用這種技術時,重要的是要確定決定每個過載能見度的判別條件是相互排斥,否則可能會產生歧義。
首先,您需要定義一些特徵元函數,它可以幫助你確定某個類是否爲葉:
// Primary template
template<typename T> struct is_leaf<T> { static const bool value = false; };
// Specializations...
template<> struct is_leaf<Leaf1> { static const bool value = true; };
template<> struct is_leaf<Leaf2> { static const bool value = true; };
...
然後,您可以使用std::enable_if
(或boost::enable_if
如果您正在使用C +工作98)來選擇該呼叫操作員的過載,應可見:
class NodeVisitor: public boost::static_visitor<void>
{
public:
// Based on the fact that boost::variant<> defines a type list called
// "types", but any other way of detecting whether we are dealing with
// a variant is OK
template<typename Node>
typename std::enable_if<
!is_same<typename Node::types, void>::value
>::type
operator()(const Node& e) const
{
boost::apply_visitor(*this, e);
}
// Based on the fact that leaf classes define a static constant value
// called "isLeaf", but any other way of detecting whether we are dealing
// with a leaf is OK
template<typename Leaf>
typename std::enable_if<is_leaf<Leaf>::value>::type
operator()(const Leaf& e) const
{
...
}
};
解決方案2:基於過載技術
如果您正在使用C++ 98和不想使用boost::enable_if
作爲替代std::enable_if
,另一種方法包括在開發重載決議和一個輔助函數的兩個重載區分未使用的參數。首先,您可以定義兩個虛擬類:
struct true_type { };
struct false_type { };
然後,你再創建is_leaf<>
元函數,妥善專業是葉類:
// Primary template
template<typename T> struct is_leaf<T> { typedef false_type type; };
// Specializations...
template<> struct is_leaf<Leaf1> { typedef true_type type; };
template<> struct is_leaf<Leaf2> { typedef true_type type; };
...
最後,創建其中的一個實例虛擬類型選擇一個輔助函數process()
的正常過載:
class NodeVisitor: public boost::static_visitor<void>
{
public:
template<typename T>
void operator()(const T& e) const
{
typedef typename is_leaf<T>::type helper;
process(e, helper());
}
template<typename Node>
void process(const Node& e, false_type) const
{
boost::apply_visitor(*this, e);
}
template<typename Leaf>
void process(const Leaf& e, true_type) const
{
...
}
};
如果你的葉類包含了一些類型定義或爲static你可以使用SFINAE C常量值 –