2016-04-14 56 views
0

我想要實現像這樣兩個簡單的抽象類:實現抽象類的無模板參數

class Hashable { 
public: 
    virtual Int hashValue() = 0; 
}; 

template <typename T> 
class Equatable { 
    virtual Bool operator == (const T& other) = 0; 
} 

這些課程給我的模板偏特的機會,在我的新字典類。

但是,我無法讓他們工作。這裏是我的字典類的聲明:

template <Hashable Key, typename Value> 
class Dictionary { 
    . 
    . 
    . 
}; 

的問題是,關鍵還應該Equatable因爲hashability應該要求它。

所以,我有兩個問題:

  1. 我們可以重寫Equatable<T>類沒有模板參數? C++是否有任何關鍵字指向類的當前類型?

  2. 在我看來,Hashable最好從Equatable繼承。如何在Hashable沒有新的模板定義(如果我的第一個問題回答是,那麼這個問題已經解決了)?

  3. 這裏最好的面向對象的方法是什麼?使用模板參數的接口類似乎很俗氣。

謝謝。

+1

我想你實際上是尋找類型類的機制,這是不是真的很好可用在C++中。有一種從C++ 11開始計劃的概念機制,但它並沒有使它成爲C++ 17(http://honermann.net/blog/?p=3) –

回答

2

你基本上是尋找的是概念,與你寫的東西,如:

template <class T> 
concept bool Hashable() 
{ 
    return requires(T t, T u) { 
     {t.hashValue()} -> size_t; 
     {t == u} -> bool; 
    }; 
} 

template <Hashable Key, class Value> 
class Dictionary { 
    ... 
}; 

但是,這甚至不會在C++ 17。

之前,我們使用void_t可以寫這樣的事情在C++ 14:

template <class...> using void_t = void; 

template <class T, class = void> 
struct Hashable : std::false_type { }; 

template <class T> 
struct Hashable<T, void_t< 
    std::enable_if_t<std::is_same<std::declval<T&>().hashValue(), std::size_t>::value>, 
    decltype(std::declval<T&>() == std::declval<T&>()) 
    >> 
: std::true_type { }; 

template <class Key, class Value> 
class Dictionary { 
    static_assert(Hashable<Key>::value, "Key must be Hashable<>"); 
    ... 
}; 

注意,在這兩種情況下,我們需要Key類型具有此功能 - 我們不要求Key幾乎繼承。這效率更高。沒有必要的虛擬調度。

這裏最好的面向對象的方法是什麼?

不使用面向對象的方法。

+0

最新的clang是否有概念,或者你知道它什麼時候可用? – Leviathlon

+0

@Leviathlon目前還不清楚何時(如果* ever *)概念將在C++標準中出現。主幹上的gcc 6.0是我意識到的唯一實現。 – Barry

+0

僅供參考,整個想法源自https://developer.apple.com/library/watchos/documentation/Swift/Reference/Swift_Hashable_Protocol/index.html – Leviathlon

1

我相信

template <Hashable Key, typename Value> 

實際上並沒有做你期望它做的事情。試想一下:

template <int Key, typename Value> class x{}; 

現在,您可以實例x<1, int>x<2, int>,但這些都不是隻是不同的對象,但不同類型的。所以,在你的情況下,你的對象將成爲類型的一部分(所以它將不得不在編譯期間生成,而不是在運行時)。

你最想而不是什麼 - 就像沃伊切赫Frohmberg在其他答覆中提到:

template <typename K, typename V> 
class Dict { 
... 
static_assert(std::is_base_of<K, Hashable>::value, "Only Hashable can be the key); 
} 

enable_if或其他一些模板魔術從type_traits包括在內。

你在找什麼是概念,甚至沒有讓C++ 17,或類型類(其他語言的版本,比如Haskell和斯卡拉)

如果你真的想用面向對象這裏的方法,去的東西,如:

template <typename Value> 
class Dict { 
    Dict(std::shared_ptr<Hashable>, Value) 
    {} 
} 

但是,它不是一個典型的實現,所以我不會推薦它

+0

是否有可能專門化一個模板參數與兩個基類(即'模板 ...')? – Leviathlon

+0

這些不是基類 - 這是你的類型參數。你的例子定義了一個帶有三個參數的模板:一個是Hashable類型,一個是Equatable類型的,另一個是任意的。你似乎模仿Haskell的typeclass語法 - 它在C++中不能以這種方式工作。如果你想在模板參數中強制使用基類依賴或任意方法,你必須使用'type_traits'。通過使用'type_traits',你可以編寫任意數量的約束條件。 –

+0

當然,我不想用三個參數來定義一個模板,我的例子只是爲了展示我想要做的事情。不管怎樣,謝謝你。 – Leviathlon