Как я могу получить специализированный шаблон для использования неспециализированной версии функции-члена? - PullRequest
3 голосов
/ 07 декабря 2008

Рассмотрим следующий код:

template <int dim>
struct vec
{
    vec normalize();
};


template <>
struct vec<3>
{
    vec cross_product(const vec& second);
    vec normalize();
};

template <int dim>
vec<dim> vec<dim>::normalize()
{
    // code to normalize vector here
    return *this;
}

int main()
{
    vec<3> direction;
    direction.normalize();
}

Компиляция этого кода приводит к следующей ошибке:

1> main.obj: ошибка LNK2019: неразрешенный внешний символ "public: struct vec <3> __thiscall vec <3> :: normalize (void)" (? Normalize @? $ Vec @ $ 02 @@ QAE? AU1 @ XZ) упоминается в функции _main

Ответы [ 3 ]

9 голосов
/ 07 декабря 2008

Вы не можете :) Вместо этого вы хотите специализировать функции-члены:

template <int dim>
struct vec
{
    // leave the function undefined for everything except dim==3
    vec cross_product(const vec& second);
    vec normalize();
};

template<>
vec<3> vec<3>::cross_product(const vec& second) {
    // ...
}

template <int dim>
vec<dim> vec<dim>::normalize()
{
    // code to normalize vector here
    return *this;
}

Другое, немного более сложное решение - использовать boost::enable_if:

template <int dim>
struct vec
{
    // function can't be called for dim != 3. Error at compile-time
    template<int dim1>
    typename boost::enable_if_c< dim == dim1 && dim1 == 3, vec<dim1> >::type 
    cross_product(const vec<dim1>& second) {
        // ...
    }
    vec normalize();

    // delegate to the template version
    void without_params() {
        // delegate
        this->without_params<dim>();
    }

private:
    // function can't be called for dim != 3. Error at compile-time
    template<int dim1>
    typename boost::enable_if_c< dim == dim1 && dim1 == 3 >::type 
    without_params() {
        // ...
    }   
};

template <int dim>
vec<dim> vec<dim>::normalize()
{
    // code to normalize vector here
    return *this;
}

Это приведет к ошибке времени компиляции, если cross_product вызывается для любого dim! = 3. Обратите внимание, что этот трюк работает только для функций с параметрами, поскольку только тогда параметр шаблона может быть автоматически выведен. Для случаев без параметров, я предоставил функцию without_parameters выше :).

2 голосов
/ 07 декабря 2008

Вы не предоставили определение vec <3> :: normalize, поэтому компоновщик, очевидно, не может ссылаться на него.

Весь смысл специализации шаблона заключается в том, что вы можете предоставить специализированные версии каждого метода. За исключением того, что вы на самом деле не делаете этого в этом случае.

1 голос
/ 07 декабря 2008

Насколько я знаю, нельзя назвать "универсальную" версию.

В качестве альтернативы вы можете определить свои универсальные реализации вне классов как функции:

template <int dim>
struct vec
{
};

namespace impl {
    template <int dim>
    vec<dim> normalize(const vec<dim>& v)
    {
        // code to normalize vector here
        return v;
    }
}

template <>
struct vec<3>
{
    vec cross_product(const vec& second);
    vec normalize() { return impl::normalize(*this); }
};


int main()
{
    vec<3> direction;
    direction.normalize();
}
...