Buradaki diğer yanıtların belirttiği gibi, bu genellikle C ++ 'da garanti edilmez. C ++ 'da, "bu sınıftan miras" dışındaki diğer kısıtlamalara dayalı genel türleri tanımlama eğilimindeyiz. Bunu gerçekten yapmak istiyorsanız, C ++ 11'de yapmak oldukça kolaydır ve <type_traits>
:
#include <type_traits>
template<typename T>
class observable_list {
static_assert(std::is_base_of<list, T>::value, "T must inherit from list");
// code here..
};
Bu, insanların C ++ 'da beklediği birçok kavramı kırıyor. Kendi özelliklerinizi tanımlamak gibi hileler kullanmak daha iyidir. Örneğin observable_list
, typedef'leri olan const_iterator
ve döndüren bir begin
ve end
üye işlevi olan herhangi bir kapsayıcı türünü kabul etmek istiyor olabilir const_iterator
. Bunu, kendisinden devralan sınıflarla sınırlarsanız list
, kendisinden devralmayan, list
ancak bu üye işlevlerini ve typedefs'i sağlayan kendi türüne sahip bir kullanıcı ,observable_list
.
Bu sorunun iki çözümü var, bunlardan biri hiçbir şeyi kısıtlamamak ve ördek tipine güvenmemek. Bu çözümün büyük bir yararı, kullanıcıların grok yapması zor olabilecek büyük miktarda hata içermesidir. Başka bir çözüm, arayüz gereksinimlerini karşılamak için sağlanan türü kısıtlamak için özellikler tanımlamaktır. Bu çözümün en büyük yanı, can sıkıcı olarak görülebilen ekstra yazı içermesidir. Ancak, olumlu tarafı kendi hata mesajlarınızı la yazabilmenizdir static_assert
.
Tamlık için yukarıdaki örneğe çözüm verilmiştir:
#include <type_traits>
template<typename...>
struct void_ {
using type = void;
};
template<typename... Args>
using Void = typename void_<Args...>::type;
template<typename T, typename = void>
struct has_const_iterator : std::false_type {};
template<typename T>
struct has_const_iterator<T, Void<typename T::const_iterator>> : std::true_type {};
struct has_begin_end_impl {
template<typename T, typename Begin = decltype(std::declval<const T&>().begin()),
typename End = decltype(std::declval<const T&>().end())>
static std::true_type test(int);
template<typename...>
static std::false_type test(...);
};
template<typename T>
struct has_begin_end : decltype(has_begin_end_impl::test<T>(0)) {};
template<typename T>
class observable_list {
static_assert(has_const_iterator<T>::value, "Must have a const_iterator typedef");
static_assert(has_begin_end<T>::value, "Must have begin and end member functions");
// code here...
};
Yukarıdaki örnekte, C ++ 11'in özelliklerini sergileyen birçok kavram bulunmaktadır. Meraklı için bazı arama terimleri varyasyon şablonları, SFINAE, SFINAE ifadesi ve tür özellikleridir.