template <typename T> Variant(const T&) // (a)
Variant(const CustomVariant&) // (b)
Не требуется преобразования для вызова (a) ;тип аргумента, DerivedVariantB
, является точным совпадением, где T = DerivedVariantB
.
Требуется преобразование из производной в базовую область для вызова (b) .Следовательно, (a) лучше, чем (b) .
Если вы вызываете конструктор с аргументом типа CustomVariant
, оба конструктора являются точнымисовпадает, поэтому (b) выбрано потому, что если все остальное равно, шаблон не является предпочтительным по сравнению с шаблоном.
Вы можете запретить использование шаблона, где T
получено из Variant
с помощью std::enable_if
:
template<typename T>
Variant(const T&,
typename std::enable_if<
!std::is_base_of<Variant, T>::value, void*
>::type = 0)
{
std::cout << "template" << std::endl;
}
Это делает шаблон не подлежащим созданию, когда T
получено из Variant
, поэтому он не будет доступен во время разрешения перегрузки.enable_if
и is_base_of
являются новыми для C ++ в C ++ 0x, и ваш компилятор и стандартная библиотека могут их поддерживать.Если нет, вы также можете найти их в C ++ TR1 или Boost.TypeTraits .