Давайте начнем с того, почему то, что у вас сейчас есть, не работает. Функция шаблона (также конструкторы) идентифицируется по своей подписи. Эта подпись включает в себя то, что представляют собой аргументы шаблона (типы, не-типы, шаблоны), их порядок, а также аргументы функций и тип возвращаемого значения (конструктор не имеет возвращаемого типа, но это не имеет отношения к тому, что мы пытаемся выполнения). Итак, то, что вы пытались сделать, включало объявление одного и того же consturctor дважды! Прежде чем определение будет рассмотрено, у вас есть дубликат декларации, что, конечно, недопустимо.
Так что мы можем сделать? Мы можем добавить параметры для каждого конструктора. И если это их дифференцирует, они могут сосуществовать. Но сосуществования недостаточно, мы хотим, чтобы разрешение перегрузки относилось к ним по-разному. Мы хотим, чтобы первый шаблонный c'or был выбран для классов, производных от T. И второй для классов, производных от SomeClass
. Можем ли мы сделать это? Да мы можем. Если мы сделаем параметр шаблона, который мы добавим, в зависимости от наших условий и неудачной замены, если условие не выполнено, эта перегрузка будет удалена из рассмотрения. Это SFINAE !
Таким образом, применяя все это на практике:
template <typename E, std::enable_if_t<!std::is_same<SomeClass,T>::value &&
std::is_convertible<E*, T*>::value>* = nullptr>
Wrapper(const E & val)
{
}
template <typename E, std::enable_if_t<std::is_convertible<E*, SomeClass*>::value>* = nullptr>
Wrapper(const E & val)
{
}
Так что же делает вышеперечисленное? Он добавляет еще один параметр шаблона с аргументом по умолчанию. Это делается условно, и если во время подстановки условие не выполняется, подпись «плохого» c'or плохо сформирована. И это не будет учитываться при разрешении перегрузки.
Я также позволил себе приспособиться к вашему состоянию. Вы, вероятно, хотите, чтобы были приняты только те классы, которые публично происходят от T
и SomeClass
. Это лучше выражено std::is_convertible
. std::is_base_of
также разрешит частное и неоднозначное множественное наследование. Я также убедился, что в случае T
равно SomeClass
мы больше не получим двух конфликтующих объявлений конструктора.