自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)
。
如果我删除了{{1}中的constexpr
,则会遇到一个if constexpr
问题,因为static_cast<float>
可以是arg (std::variant)
(在访问者中进行了进一步处理)。
为什么简单条件std::nullopt
无法建立?
非常感谢您的回答。
编辑:
也许我的问题与此有关:
constexpr
当条件评估操作的左侧操作数在constexpr上下文中无效时,Visual Studio 2017会正确引发错误。以下代码在Visual Studio 2015中编译,但在Visual Studio 2017中不能编译(C3615 constexpr函数'f'无法产生常量表达式):
abs(cents) > 0.01f
要更正此错误,请将array :: size()函数声明为constexpr或从f中删除constexpr限定符。
EDIT2:
如果我在行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
}
上注释(在没有阈值条件的情况下调用if (abs(cents) > 0.01f)
),则代码可以正常运行。因此,虽然microtone(cents)
是0.01f
,而float constant
是cents
,但是唯一的问题来自对float temporary variable
函数的调用。如我所见,std::abs
不是constexpr函数。
如何解决这一点而无需编写内部版本的constexpr有效的std :: abs?
答案 0 :(得分:0)
您是否看到过MS Developer错误报告https://developercommunity.visualstudio.com/content/problem/323938/broken-parsing-of-greater-than-comparison-operator.html
上面的错误似乎已在2019 Preview中修复。 但是在此之前,如错误报告中所述。
下面将最小化上述代码以重现vs 2017中的错误。 该修复程序按访问顺序标记。 if constexpr(...; if(...> ....)表达式由()括起来或>运算符的逆逻辑 注意:访问后的“>”;如果constexpr序列在其他情况下可能导致问题。
#include <tuple>
#include <variant>
#include <optional>
inline std::tuple<float, float> _convertCentsToAlterAndCents(float shift)
{
return std::tuple{shift, shift};
}
//using AccidentalVar = std::variant<std::nullopt_t, int, float, double, const char*, std::string, Accidental, Accidental::Ptr>;
using AccidentalVar = std::variant<std::nullopt_t, int, float, double, const char*>;
void microtone(float cents) {}
//void Pitch::accidental(AccidentalVar value)
void test(AccidentalVar value)
{
//std::visit([this](auto&& arg)
std::visit([&](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) // error in vs 2017
if ( ( abs(cents) > 0.01f ) ) // FIX 1 or
//if( 0.01f <= abs(cents) ) // or FIX 2
microtone(cents);
}
// remaining code removed...
},
value);
}