【发布时间】:2018-12-06 13:40:12
【问题描述】:
这里有一些代码:
#include <iostream>
#include <functional>
#include <string>
#include <variant>
namespace detail
{
std::string Foo(const double val)
{
return std::to_string(val);
}
}
using Value = std::variant<std::monostate, double, int, bool, std::string>;
struct ReadStore {};
struct ValueException : std::runtime_error {};
using PrintConvType = std::function<Value(const Value&, ReadStore&)>;
template <typename InType, typename OutType, typename CallableType, CallableType Callable, bool Strict>
Value ConvWrapperImpl(const Value& value)
{
if constexpr (std::is_same_v<InType, Value>)
{
return Callable(value);
}
else
{
if (value.index() != 0)
{
const auto* ptr = std::get_if<InType>(&value);
if (ptr)
return Callable(*ptr);
}
return value;
}
}
template <typename T1, typename T2, T2 (*Callable)(const T1&), bool Strict = false>
Value ConvWrapper(const Value& value, ReadStore&)
{
return ConvWrapperImpl<T1, T2, decltype(Callable), Callable, Strict>(value);
}
template <typename T1, typename T2, T2 (*Callable)(T1), bool Strict = false>
Value ConvWrapper(const Value& value, ReadStore&)
{
return ConvWrapperImpl<T1, T2, decltype(Callable), Callable, Strict>(value);
}
int main()
{
using namespace detail;
ReadStore store;
PrintConvType func = ConvWrapper<double, std::string, Foo>;
Value result = func(3.14159, store);
std::cout << std::get<std::string>(result) << '\n';
}
这是一个人为的 MCVE,但原始项目中的总体思路是提供一种简写形式,用于将 Value 转换为某些回调函数的适当参数类型,并将所述函数的返回类型转换回再次发送至Value。
这很好 under GCC 和 Clang,但我的 Visual Studio 2017 (v15.7.2) 出错了:
error C2440: 'specialization': cannot convert from 'std::string (__cdecl *)(const double)' to 'std::string (__cdecl *)(const double &)'
note: This conversion requires a reinterpret_cast, a C-style cast or a function-style cast
error C2973: 'convWrapper': invalid template argument 'std::string (__cdecl *)(const double)'
note: see declaration of 'ConvWrapper'
根据最后一条注释链接到的位置,它似乎选择了错误的ConvWrapper,然后当Callable 签名不匹配时表现得非常惊讶。
奇怪的是on Godbolt with the same compiler selected, the code is accepted。
是否有可能影响此的配置?是我吗?
我该如何解决?是配置更改还是代码更改?
【问题讨论】:
-
你试过去掉“多余的”
const->std::string Foo(double val)吗? -
@Jarod42 是的。这不是多余的:(好吧,无论如何,不在定义中。
-
我通过将一致性模式从
Yes (permissive-)更改为No并使用/std:c++17或/std:latest来获得使用MSVS 2017 (15.8.7) 编译的代码 -
@NathanOliver Ah 有趣 -
/permissive-让我崩溃了 :) (我真的应该复制 Godbolt 演示中的所有标志) -
它为我编译,只有“/std:c++17”,编译器版本 19.16.27023.1。您的编译器版本是什么(cl.exe 打印的版本)?
标签: c++ visual-studio visual-studio-2017 c++17