VS 选错专业了吗?为啥?

Posted

技术标签:

【中文标题】VS 选错专业了吗?为啥?【英文标题】:Is VS picking the wrong specialisation? Why?VS 选错专业了吗?为什么? 【发布时间】: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 打印的版本)? 【参考方案1】:

导致问题的编译器标志是/permissive- 一致性标志。从编译器命令中删除它或在 Debug -> "name of project" properties -> C/C++ -> Language -> Conformance Mode 中将其更改为 No 将使其编译。

【讨论】:

【参考方案2】:

您可以通过将typename CallableType, CallableType Callable 替换为auto Callable 来避免使用c++17 的重载。 那么MSVC就不需要在类型之间进行转换了。

template <typename InType, auto 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, auto Callable, bool Strict = false>
Value ConvWrapper(const Value& value, ReadStore&)

    return ConvWrapperImpl<T1, Callable, Strict>(value);

类似用法(ConvWrapper&lt;double, &amp;Foo&gt; 而不是ConvWrapper&lt;double, std::string, &amp;Foo&gt;):

int main()

    using namespace detail;

    ReadStore store;
    PrintConvType func = ConvWrapper<double, &Foo>;

    Value result = func(3.14159, store);
     std::cout << std::get<std::string>(result) << '\n';

Demo

【讨论】:

这就是我最终要做的,所以我可以保持一致性模式。有趣的是,这似乎证实了 VS 选择了错误的过载这一观察结果。也许吧。 感谢您的宝贵时间!

以上是关于VS 选错专业了吗?为啥?的主要内容,如果未能解决你的问题,请参考以下文章

现在的计算机专业(比如机器学习)已经沦为调包专业了吗?

华东五校,计算机专业,哪一个大学最强,为啥?

灵魂拷问:机器学习深度学习专业已经沦为调包专业了吗?

福利妞美国商科留学:金融/项目管理硕士专业,这些问题你了解了吗?

vs2017 企业版和专业版的区别

又一个财务专业被双一流高校撤销!人工智能要取代了吗?