1

考慮以下設置:替代品的std :: enable_if和模板的模板明確的重載參數

template< typename Held > 
class Node{ 
    //... 
}; 

template< typename Held > 
class vNode{ 
    //... 
}; 

template <typename... Graphs> 
class Branch{ 
    //... 
}; 

template <typename...> class Graph; // undefined 

template< 
    typename node_t 
> class Graph<node_t>{ //specialization for an ending node 
    //... 
}; 

template< 
    typename node_t, 
    typename... Graphs 
> class Graph< node_t, Branch< Graphs...> >{ //specialization for a mid-graph node 
    //... 
}; 

template< 
    template <typename> class node_t, 
    typename Held 
> void f(Graph< Node<Held> >) { 
    //stuff A on a node 
} 

template< 
    template <typename> class node_t, 
    typename Held 
> void f(Graph< const Node<Held> >) { 
    //stuff A on a const node 
} 

template< 
    template <typename> class node_t, 
    typename Held 
> void f(Graph< vNode<Held> >) { 
    //stuff B on a virtual node 
} 

template< 
    template <typename> class node_t, 
    typename Held 
> void f(Graph< const vNode<Held> >) { 
    //stuff B on a virtual const node 
} 

template< 
    template <typename> class node_t, 
    typename Held, 
    typename... Graphs 
> void f(Graph< Node<Held>, Branch<Graphs...>>) { 
    //stuff C on a node with a branch 
} 

template< 
    template <typename> class node_t, 
    typename Held, 
    typename... Graphs 
> void f(Graph< const Node<Held>, Branch<Graphs...> >) { 
    //stuff C on a const node with a branch 
} 

template< 
    template <typename> class node_t, 
    typename Held, 
    typename... Graphs 
> void f(Graph< vNode<Held>, Branch<Graphs...> >) { 
    //stuff D on a virtual node with a branch 
} 

template< 
    template <typename> class node_t, 
    typename Held, 
    typename... Graphs 
> void f(Graph< const vNode<Held>, Branch<Graphs...> >) { 
    //stuff D on a virtual const node with a branch 
} 

換句話說 - 我創建一個表示圖的類型。節點可以是正常的,或虛擬的,常量和非常量。一個圖可以包含單個節點,或一個節點和一個圖分支。當我創建一個函數f我希望它是常量中性(在圖形中的節點的常量和非常量版本上做同樣的事情,但在分支和未分支的圖上不同)。我必須:

  1. 重複的代碼?
  2. 使用std::enable_if黑客?

    1. 重複的代碼重複錯誤,所以它不是最優的。
    2. std :: enable_if在我的情況下產生錯誤的錯誤信息。

是否有一個更聰明的解決問題的方法,這將使f接受const和non-const的節點?

+1

爲什麼不簡單地'template void f(圖)'並且讓'T'被適當地推導出來?您可以隨時使用特徵類輕鬆提取節點類型。 – 2014-09-11 11:30:13

+0

爲什麼'Graph < node_t >'和'Graph >'如果它們具有不同的實現,接口並且使用方法不同,那麼它們是'相同'模板?還是有對待他們的功能相同?例如,您可以編寫一個工廠模板,根據它是否爲終端返回不同的類型。 – Yakk 2014-09-11 14:11:32

+0

@Yakk:有兩個原因:1.一個'Graph'來自'Branch <>',它是一個'std :: tuple'包裝器。由於'std :: tuple <>'不是零大小,我認爲空基優化不適用。 2.有遍歷'Graph'的遞歸函數,並且在終端節點上終止它們需要函數超載。 Graph >'的重載與'Graph '沒有多大區別,後者產生更短的錯誤並且意圖更明確。 @TC:這是一個很好的想法,我去了。一如既往地感謝你,這應該作爲答案發布。 – tsuki 2014-09-11 14:29:57

回答

1

而不是使用模板的模板參數,並有一個極大的重載,只是使用類型模板參數:

template<class T> void f(Graph<T>) { /*...*/ } 

T會被推斷爲Node<Foo>vNode<Foo>const Node<Foo>等適當的。如果NodevNode很重要,則可以始終使用簡單的特徵類提取節點的類型。同樣,您可以使用static_assert以及特質類別來確保TNodevNode的特化。