MSVC не может сделать математику в зависимости от параметров шаблона, это ошибка? - PullRequest
0 голосов
/ 03 октября 2018

Я не смог найти очень подходящее название для этого вопроса, не сделав его слишком длинным, поэтому он может быть не очень точным.У меня есть класс clamped_value, который хранит значение и гарантирует, что значение остается в пределах известной границы времени компиляции.Теперь я использую этот класс следующим образом:

class SomeClass
{
    using value_type = int;
    using percent_type = clamped_value<value_type, 0, 100>;
};

Все это прекрасно работает, и я приступил к добавлению Precision параметра шаблона к SomeClass

template<int Precision>
class SomeClass
{
    using value_type = int;
    using percent_type = clamped_value<value_type, 0, 100 * (Precision + 1)>;
};

Внезапноразрывы кода!Выдает много ошибок о функциях в clamped_value.hpp, которые уже определены (я уверен, что заголовочные стражи там правы).Я решил протестировать код с помощью Gcc ( см. Пример coliru здесь ), и он работал просто отлично.Компиляция с Clang также работала.Это ошибка в MSVC?

Версия MSVC - 15.7.2.

ОБНОВЛЕНИЕ

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

template<class T, int N, int M>
class clamped_value
{
public:
#define GEN_F(f) void f() {}

    GEN_F(a)
    GEN_F(b)
};

template<int N = 0>
class SomeClass
{
    using percent_type = clamped_value<int, 0, 100 * N>;

public:
    SomeClass()
    {
        percent_type p;
        p.a();
    }
};



int main()
{
    SomeClass<> a;
}

Дополнительная ссылка на coliru: https://coliru.stacked -crooked.com / a / a2d612a292e72198

Новое обновление: обновление VS до последней версии не устранило проблему.Делаем лучше MCVE сейчас.

1 Ответ

0 голосов
/ 04 октября 2018

После еще нескольких работ я наконец-то заметил, что случилось.Сначала мне удалось повторить ошибку на gcc здесь .Когда я начал больше думать об этом, я наконец обнаружил это.В clamped_value есть макрос:

#define GEN_ARITHMETIC_OP(op) \
template<typename Ty, Ty TMin, Ty TMax, typename U, U UMin, U UMax> \
friend constexpr detail::common_clamped_value_t<Ty, TMin, TMax, U, UMin, UMax> \
operator op(clamped_value<Ty, TMin, TMax> const& lhs, clamped_value<U, UMin, UMax> const& rhs) \
{ \
    auto val = detail::common_clamped_value_t<Ty, TMin, TMax, U, UMin, UMax>(lhs.m_value op rhs.m_value); \
    val.clamp(); \
    return val; \
}

Теперь проблема в том, что первый clamped_value является шаблонным и, таким образом, работает для всех clamped_value.Поэтому, если я создаю экземпляр только одного clamped_value, все работает.Но с того момента, как я использую новый набор параметров шаблона, макрос снова раскрывается , и оператор определяется дважды.Простым решением было изменить определение макроса, чтобы оно работало только для текущего экземпляра типа:

#define GEN_ARITHMETIC_OP(op) \
template<typename U, U UMin, U UMax> \
friend constexpr detail::common_clamped_value_t<T, Min, Max, U, UMin, UMax> \
operator op(clamped_value const& lhs, clamped_value<U, UMin, UMax> const& rhs) \
{ \
    auto val = detail::common_clamped_value_t<T, Min, Max, U, UMin, UMax>(lhs.m_value op rhs.m_value); \
    val.clamp(); \
    return val; \
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...