Член класса шаблонов против неоднозначности функции-члена - PullRequest
0 голосов
/ 26 января 2019

Я разрабатываю библиотеку только для заголовков для автоматического / алгоритмического дифференцирования. Цель состоит в том, чтобы иметь возможность просто изменить тип переменных, передаваемых в функцию, и вычислить первую и вторую производные. Для этого я создал шаблонный класс, который позволяет программисту выбирать тип хранилища для закрытых членов данных. Ниже приведен фрагмент кода с перегрузкой оператора-нарушителя.

template <typename storage_t>
class HyperDual
{
    template <typename T> friend class HyperDual;
    public:
        template <typename T>
        HyperDual<storage_t> operator+(const HyperDual<T>& rhs) const
        {
            HyperDual<storage_t> sum;
            for (size_t i = 0; i < this->values.size(); i++)
                sum.values[i] = this->values[i] + rhs.values[i];
            return sum;
        }
    protected:
        std::vector<storage_t> values;
};

Позже, чтобы максимизировать универсальность, я предоставляю шаблонные функции, позволяющие взаимодействие.

template <typename storage_t, typename T>
HyperDual<storage_t> operator+(const HyperDual<storage_t>& lhs, const T& rhs)
{
    static_assert(std::is_arithmetic<T>::value && !(std::is_same<T, char>::value), "RHS must be numeric");
    return HyperDual<storage_t>(lhs.values[0] + rhs);
}

template <typename storage_t, typename T>
HyperDual<storage_t> operator+(const T& lhs, const HyperDual<storage_t>& rhs)
{
    static_assert(std::is_arithmetic<T>::value && !(std::is_same<T, char>::value), "LHS must be numeric");
    return HyperDual<storage_t>(lhs + rhs.values[0]);
}

С чем я сталкиваюсь, так это с тем, что компилятор пытается создать экземпляр второй функции-члена, не являющейся членом.

#include "hyperspace.h"

int main()
{
    HyperDual<long double> one(1); // There is an appropriate constructor
    HyperDual<double> two(2);

    one + two;

    return 0;
}

Я получаю сгенерированную static_assert ошибку "LHS должен быть числовым" для этого. Как бы я разрешил эту двусмысленность?

Ответы [ 2 ]

0 голосов
/ 27 января 2019

Хорошо. Я нашел свою проблему. Это сводится к разнице между static_assert и std :: enable_if

Заменив объявление моего шаблона и удалив static_assert, я получил эквивалентную функциональность:

template <typename storage_t, typename T,
          typename = typename std::enable_if<std::is_arithmetic<T>::value && !std::is_same<T, char>::value>::type>
HyperDual<storage_t> operator+(const T& lhs, const HyperDual<storage_t>& rhs)
{
    return HyperDual<storage_t>(lhs + rhs.value());
}

(Мелкие детали, но rhs.values[0] был заменен на rhs.value(). Это не имело никакого отношения к проблеме с шаблоном, но было связано с доступом членов.

0 голосов
/ 27 января 2019

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

template <typename storage_t, typename T, typename = enable_if_t<std::is_arithmetic<T>::value && !(std::is_same<T, char>::value)>>
HyperDual<storage_t> operator+(const HyperDual<storage_t>& lhs, const T& rhs)
{
    static_assert(std::is_arithmetic<T>::value && !(std::is_same<T, char>::value), "RHS must be numeric");
    return HyperDual<storage_t>(lhs.values[0] + rhs);
}

static_assert может быть продублирован здесь.

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