Не удается правильно создать экземпляр шаблона при использовании функциональной библиотеки C ++ - PullRequest
2 голосов
/ 03 августа 2011

Я пытаюсь создать класс векторов фиксированного размера, чтобы использовать в основном для геометрических целей, где длина вектора не меняется:

template<typename T, int n>
class FixedVector
{
private:
    T m_rV[n]; // this is the only data member
     public:
              // class function members
              ...
}

Это дает преимущество при проверке компилятором операций с векторами несовместимого размера.

У меня проблемы при попытке построить оператор * для этого класса (примечание: он не является членом). Этот оператор должен умножить вектор на скаляр, например: 3 * [1,2,3] = [3,6,9].

template<typename T, int n>
FixedVector<T,n> operator*(const T   &rX, const FixedVector<T,n> &cV) const
{   typename std::pointer_to_binary_function<T,T,T> op=(util::times<T>);
    FixedVector<T,n> cT(cV, std::bind1st(op, rX));
    return cT;
}

где times - функция умножения скалярного члена вектора

template<typename T>
inline T times(const T &t1, const T &t2)
{   return t1*t2;
}

код для конструктора в строке 4:

template<typename T, int n>
FixedVector<T,n>::FixedVector(const T rV[n], T (*f)(const T &)) 
{   util::copy(m_rV, rV, n, f);
}

, pointer_to_binary_function и bind1st являются функциями STL из заголовка (те, кто может помочь, должны это знать уже).

Я получаю следующую ошибку компилятора в Visual Studio 2005 при вызове

    util::FixedVector<int,4> x; 3*x;

fixed_vector.hpp(212) : error 2440:
        'initializing' : cannot convert from 'T (__cdecl *)(const T &,const T &)'
         to 'std::pointer_to_binary_function<_Arg1,_Arg2,_Result>'
with
[
       _Arg1=int,
        _Arg2=int,
        _Result=int
    ]
    No constructor could take the source type, or constructor overload resolution was ambiguous
    testproject.cpp(18) : see reference to function template instantiation 'util::FixedVector<T,n> util::operator *<T,4>(const T &,const util::FixedVector<T,n> &)' being compiled
   with
    [
        T=int,
        n=4
    ]

Похоже, что имя типа std :: pointer_to_binary_function правильно создан для станд :: pointer_to_binary_function Тем не менее, времена все еще остаются его основной подписью: 'T (__cdecl *) (const T &, const T &)


--- ПОСЛЕ НЕКОТОРОГО РЕДАКТИРОВАНИЯ ----------------------------------------- -----------------------

Мне было указано, что функция, которую мой конструктор запрашивает в качестве параметра простую функцию: T (*) (const T & t1, const T & t2) и что функциональные объекты STL не будут приняты. Ссылка здесь STL for_each послужила руководством по внесению исправлений.

Я начал переходить от функции util :: copy, вызываемой конструктором.

От: шаблон недействительная копия (T * dst, const T * src, size_t n, T (* f) (const T &)) {for (; n> 0; n--, dst ++, src ++) {* dst = f (* src); }}

стало

    template<typename T, typename Function>
void copy(T *dst, const T *src, size_t n, Function f)
{   for (; n>0; n--, dst++, src++)
    {   *dst = (*f)(*src);
}   }

Затем сам конструктор был создан по шаблону. От:

template<typename T, int n>
FixedVector<T,n>::FixedVector(const T rV[n], T (*f)(const T &)) 
{   util::copy(m_rV, rV, n, f);
}

сейчас

     template<typename T, int n>
template<class Function>
FixedVector<T,n>::FixedVector(const FixedVector<T,n> &cV, Function f)
{   util::copy(m_rV, cV.m_rV, n, f);
}

Также добавлены некоторые константы в параметры создания шаблона:

template<typename T, int n>
FixedVector<T,n> operator*(const T   &rX, const FixedVector<T,n> &cV)
{   typename std::pointer_to_binary_function<const T,const T,T> op(times<T>);
    FixedVector<T,n> cT(cV, std::bind1st(op, rX));
    return cT;
}

Но я все еще получаю ту же ошибку (только то, что T был заменен на const T; обратите внимание, что добавление & для указания ссылки (const T &) вызовет ошибку, и кажется, что у шаблонов есть проблемы с этим, Boost и TR1 создание специальных решений для решения этой проблемы - см. справочник Wikipedia TR1 ).

Точная строка ошибки такова:

typename std::pointer_to_binary_function<const T,const T,T> op(times<T>);

Так что я даже не дохожу до конструктора.

Я был бы очень благодарен за некоторые дополнительные идеи.

Ответы [ 2 ]

2 голосов
/ 03 августа 2011

Ваша функция util::times имеет подпись:

T times(const T&, const T&)

но в этой строке:

typename std::pointer_to_binary_function<T,T,T> op=(util::times<T>);

конструктор std::pointer_to_binary_function ожидает:

T times(T, T)

Это можно исправить, используя const T& в качестве параметров шаблона аргумента:

typename std::pointer_to_binary_function<const T&, const T&, T> op(util::times<T>);

Обратите внимание, что я удалил =, чтобы использовать здесь явную запись конструктора. По крайней мере в (моем) GCC синтаксис присваивания компилятором отклоняется.

Поскольку вы создаете двоичный функтор, который выполняет умножение, вместо пользовательской функции times и оболочки-функтора, вы можете напрямую использовать std::multiplies для достижения того же:

std::multiplies<T> op;

Обратите внимание, что в следующей строке

FixedVector<T,n> cT(cV, std::bind1st(op, rX));

вы вызываете конструктор, который принимает FixedVector<T, n> в качестве первого аргумента и унарный функтор в качестве второго. Это несовместимо с кодом конструктора, который вы разместили:

template<typename T, int n>
FixedVector<T,n>::FixedVector(const T rV[n], T (*f)(const T &)) 
{   util::copy(m_rV, rV, n, f);
}

, поскольку он принимает простой массив и указатель на функцию.

1 голос
/ 03 августа 2011
template<typename T, int n>
FixedVector<T,n>::FixedVector(const T rV[n], T (*f)(const T &)) 
{   util::copy(m_rV, rV, n, f);
}

Вы не можете преобразовать в указатель на функцию любой функциональный объект с состоянием, и даже тогда, только лямбда-выражения C ++ 0x без состояния. Вы должны взять шаблонный функциональный объект или полиморфный объект, такой как function, найденный в Boost, TR1 и C ++ 0x.

Кроме того, это невероятно неясно. Почему бы просто не сделать регулярное умножение? Это было бы намного проще, чем этот подход.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...