Ограничить шаблонную функцию базовыми и производными типами? - PullRequest
5 голосов
/ 03 ноября 2011

У меня есть базовый класс шаблона:

template<typename T, std::size_t Size>
class VectorT
{
public:
    typedef T data_type;
}

и несколько специализированных производных классов:

template<typename T>
class Vector2d : public VectorT<T, 2U>
{ // some specialised functions }

template<typename T>
class Vector3d : public VectorT<T, 3U>
{  // some other specialised functions }

, и они работают нормально.Однако у меня есть несколько автономных функций для операторов.Например:

template<typename T, size_t Size>
VectorT<T, Size> operator*(T lhs, const VectorT<T, Size>& rhs)
{
    ... 
}

К сожалению, они не работают для моих производных классов, потому что они возвращают VectorT<T, Size> вместо Vector2d<T>.

Так что я попытался с

template<V>
V operator*(typename V::data_type lhs, const V& rhs)
{
    ... 
}

и это прекрасно работает, однако это может привести к неоднозначности, потому что это впитывает что-либо еще с членом data_type.

Как мне обойти это: как я могу написать безопасные функции типа, которые работают толькос моей векторной базой или какими-либо производными от?

Я пытаюсь обойти необходимость повторного объявления и переопределения операторов снова для подклассов.

Ответы [ 2 ]

7 голосов
/ 03 ноября 2011

Вы можете добавить еще один базовый класс, который не зависит от параметров шаблона, и использовать SFINAE , чтобы отключить вызовы для типов, отличных от таких базовых:

struct VectorBase {};

template< typename T, std::size_t Size >
class VectorT : public VectorBase { ... }

template< typename V >
typename boost::enable_if< boost::is_base_of< VectorBase, V >, V >::type
operator*( V lhs, V const& rhs ){ ... }

Обратите внимание, что is_base_of< X, X > всегда true, поэтому эта функция будет работать для еще одного типа, чем требуется, а именно для базового класса VectorBase.

Если вы используете компилятор, которыйреализует TR1, вы можете заменить boost:: на std:: в обоих местах, где используется.

1 голос
/ 03 ноября 2011

Вы попали в необычную ситуацию, из которой нет «приятного» пути. Вы можете:

  1. Проверка типа во время выполнения (или во время компиляции, вероятно, Boost может сделать это)
  2. Возьмите VectorT<>& и используйте его вместо создания нового VectorT внутри функции и его возврата. Таким образом, вы также можете использовать подклассы VectorT по ссылке. Это заставило бы вас использовать функцию вместо оператора.
  3. Делай, что сказал К-балл.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...