Начиная с последней версии VS2017, этот код не работает, в то время как в предыдущем выпуске точно такая же сборка кода:
inline std::tuple<float, float> _convertCentsToAlterAndCents (float shift);
using AccidentalVar = std::variant<std::nullopt_t, int, float, double, const char*, std::string, Accidental, Accidental::Ptr>;
void Pitch::accidental(AccidentalVar value)
{
std::visit([this](auto&& arg)
{
using T = std::remove_cv_t<std::remove_reference_t<decltype(arg)>>;
if constexpr (std::is_same_v<T, int> ||
std::is_same_v<T, float> ||
std::is_same_v<T, double>)
{
auto [alter, cents] = _convertCentsToAlterAndCents(static_cast<float>(arg) * 100.f);
_accidental = std::make_shared<Accidental>(alter);
if (abs(cents) > 0.01f)
microtone(cents);
}
else
if constexpr (std::is_same_v<T, const char*> ||
std::is_same_v<T, std::string>)
{
_accidental = std::make_shared<Accidental>(arg);
}
else
if constexpr (std::is_same_v<T, Accidental::Ptr>)
{
_accidental = (arg != nullptr) ? arg->deepcopy() : arg;
}
else
if constexpr (std::is_same_v<T, Accidental>)
{
_accidental = arg.deepcopy();
}
else
if constexpr (std::is_same_v<T, std::nullopt_t>)
{
_accidental = nullptr;
}
},
value);
}
Ошибка C2760, unexcepted token '>'
в строке if (abs(cents) > 0.01f)
.
Если я удаляю constexpr
в if constexpr
, я получаю проблему static_cast<float>
, потому что arg (std::variant)
может быть std::nullopt
(далее обрабатывается в посетителе).
Почемупростое условие abs(cents) > 0.01f
не удалось построить?
Большое спасибо за ваш ответ.
РЕДАКТИРОВАТЬ:
Может быть, моя проблема связана с этим:
constexpr
Visual Studio 2017 правильно выдает ошибку, когда левый операнд операции условной оценки недопустим в контексте constexpr.Следующий код компилируется в Visual Studio 2015, но не в Visual Studio 2017 (функция constexpr C3615 'f' не может привести к константному выражению):
template<int N>
struct array
{
int size() const { return N; }
};
constexpr bool f(const array<1> &arr)
{
return arr.size() == 10 || arr.size() == 11; // C3615
}
Чтобы исправить ошибку, либо объявите array :: size() работает как constexpr или удаляет квалификатор constexpr из f.
source: https://docs.microsoft.com/fr-fr/cpp/cpp-conformance-improvements-2017?view=vs-2017#bug-fixes-in-visual-studio-versions-150-153update153-155update155-157update157-and-158update158
EDIT2: Если я прокомментирую строку if (abs(cents) > 0.01f)
(вызов microtone(cents)
без порогового условия), код строится нормально.Таким образом, хотя 0.01f
- это float constant
, а cents
- float temporary variable
, единственная проблема возникает из-за вызова функции std::abs
.Как я вижу, std::abs
не является функцией constexpr.
Как решить эту проблему без записи внутренней версии std :: abs, которая является действительной constexpr?