有多種方法可以解決這個問題,但我認爲這可能適用於您。這個想法是你定義了一個基類,你的類(B
)從中繼承。基類是帶有一個bool參數的類模板,並且根據此參數的值確定或未定義find成員。作爲模板參數傳遞的值取決於您爲幾種可能類型A
定義的類型特徵。
Warning:template metaprogramming below。
讓我們從類型特徵開始。我假設可能類型的A
(這是一個模板的模板參數)是一樣的東西vector
,map
等:
template <template <typename ...> class Container>
struct EnableKeyFind
{
static int const value = false; // fallback
};
template <>
struct EnableKeyFind<std::map>
{
static int const value = true;
};
template <>
struct EnableKeyFind<std::unordered_map>
{
static int const value = true;
};
在話,上述狀態,應該有限定的find
構件時A == std::map
或A == std::unordered_map
。在所有其他情況下,非專門化模板是安裝的,其中value == false
,即沒有find
成員。您可以添加其他專業化來擴展此原則。
接下來,讓我們定義的基類:
template <typename Container, bool Enable>
class Base
{
Container &d_cont; // Base-class should have access to the container
public:
Base(Container &cont): d_cont(cont) {}
template <typename KeyType, typename ValueType>
bool find(KeyType const &key, ValueType const &val);
/* An alternative implementation would be where you use
Container::key_type and Container::value_type and get rid of
the function-template. This would require the Container-class
to have STL-like semantics. Pick whichever you prefer. */
};
// Specialization for 'false': no implementation
template <typename Container>
class Base<Container, false>
{
public:
Base(Container &cont) {}
};
基類是專門針對該Enable
模板非類型參數是false
的情況。在這種情況下,它的實現幾乎是微不足道的(除了構造函數仍然需要相同的簽名)。
現在讓我們來看看修改後的B
類(我不停的非描述性的名稱貼近的問題):
template <template <typename ...> class A, typename ... Types>
class B: public Base<A<Types ...>, EnableKeyFind<A>::value>
{
typedef A<Types ...> AType;
typedef Base<AType, EnableKeyFind<A>::value> BaseType;
AType a1;
public:
B():
BaseType(a1) // provide the base with access to a1
{}
};
因爲不同的容器類型,如vector
和map
,需要不同數量我通過使它成爲一個可變參數模板來概括類模板。它現在可以存儲任何類型的容器。它繼承自Base
,並使用類型特徵EnableKeyFind<A>
來確定它是否應繼承自Base<Container, true>
或(專業化)Base<Container, false>
。
一個典型的用例:
int main()
{
B<vector, int> b1;
b1.find(1, 1); // error: has no member find
B<map, string, int> b2;
b2.find(1, 1);
}
我希望這有助於。無論如何,這是一個有趣的小練習。
此方法的一個可能的缺點可能是您的用戶應該專門爲他們的特定容器專門設計了EnableKeyFind
類模板,前提是他們希望find()
可用。我不知道這是否太多問你的用戶,但你可以隨時提供給他們一個宏,如果你想隱藏的細節:
define ENABLE_KEYFIND(Container) \
template <>\
struct EnableKeyFind<Container>\
{ static int const value = true; };
我2美分:具有相同的類作爲兩個一個集合和一個關聯數組不應該通過策略來處理。這兩個數據結構有不同的目的和語義。 –
「策略」是指作爲模板參數傳遞的布爾值,對吧? – 5gon12eder
您可以添加另一個模板參數(bool,如5gon12eder建議),默認值取決於A參數:'bool KeyFind = Policy :: value'。這樣,您可以預定義一組已知可能類型的「A」(包括後備案例)的行爲。這對您的應用程序可能有意義或無意義。如果確實如此,並且您想了解更多信息,請告訴我,我會發布更詳細的答案。 – JorenHeit