Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/138.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 检测到带有std::experimental::的奇怪MSVC行为_C++_C++14_Sfinae_C++17 - Fatal编程技术网

C++ 检测到带有std::experimental::的奇怪MSVC行为

C++ 检测到带有std::experimental::的奇怪MSVC行为,c++,c++14,sfinae,c++17,C++,C++14,Sfinae,C++17,我实现了std::experimental::is_detectedbased(部分代码低于+working repo) 它在G++和Clang++上运行良好,但在MSVC中会导致奇怪的错误行为:被检测到似乎总是bool\u常量 在这里,您可以使用gcc 5.x查看正确的结果: 但对于MSVC 19(VS2015附带),测试总是成功的: Z:\>cl /EHsc test.cxx .... Z:\>test true, true 那么,这是编译器中已知的错误吗?它是否与表达式SF

我实现了
std::experimental::is_detected
based(部分代码低于+working repo)

它在G++和Clang++上运行良好,但在MSVC中会导致奇怪的错误行为:
被检测到
似乎总是
bool\u常量

在这里,您可以使用gcc 5.x查看正确的结果:

但对于MSVC 19(VS2015附带),测试总是成功的:

Z:\>cl /EHsc test.cxx
....
Z:\>test
true, true
那么,这是编译器中已知的错误吗?它是否与表达式SFINAE未正确实现有关?有什么方法可以让这项工作顺利进行吗

谢谢大家!


下面是再现错误的部分代码(除了检测到
以增加易读性之外,我省略了接口的其余部分):


编译上述代码需要C++11编译器,而MSVC 2015不是C++11编译器

您在C++11遵从性方面遇到的特殊缺陷被microsoft称为“expression SFINAE”。留心它被修好了

基本上,
decltype
不能用于SFINAE。用外行的话说,SFINAE是一种用于选择模板函数或类重载的技术


通常不存在解决方案。

< P>这是一个解决方案,它与最近的MSVC(用VisualC++ 19.00 .24720.0进行了测试):

#包括
模板
使用void\u t=void;
命名空间内部
{
模板
结构检测\u impl
{
使用值_t=V;
使用类型=D;
};
模板
自动检测检查(字符)
->检测\u impl;
模板
自动检测检查(int)
->decltype(void_t(),
检测_impl{});
模板
结构检测:decltype(检测\检查(0)){};
}
非等结构
{
nonesoch()=删除;
~nonesoch()=删除;
非等(非等常数&)=删除;
void运算符=(非等常数&)=删除;
};
模板类检查,typename。。。Args>
使用is_detected=typename internal::detect::value\u t;

(dummy
void
参数现在未使用,只是为了保持实现的其余部分完好无损。)

如果您正在使用基本VS2015进行此操作,请尝试至少更新1。添加了部分表达式SFINAE支持。@chris很遗憾,我已经在使用最新的CTP版本。我想说它不是一个符合标准的编译器。它确实支持大多数C++11/14功能(请看我的编辑),那么为什么直接应用void_t习惯用法是有效的,而使用detect_impl的间接方法则不行呢?@Naschkatze可能。他们的编译器在
decltype
下的行为往往是脆弱的(而不是“显然不工作”)。有时我能让它发挥作用,但除非能找到它们的来源,否则我无法预测。@NathanOliver你比我更仁慈。这是允许的。公平地说,它并不假装是一个C++11编译器:
\uu cplusplus==199711L
;)
#include <iostream>

// void_t: void type alias
template< typename... >
using void_t = void;
//

namespace internal
{
    // Fallback case
    template<   typename D,
                typename Void,
                template< typename... > class Check,
                typename... Args 
            >
    struct detect_impl
    {
        using value_t = std::false_type;
        using type = D;
    };


    // Check succeeded
    template<   typename D,
                template< typename... > class Check,
                typename... Args 
            >
    struct detect_impl
        < D, void_t< Check<Args...> >, Check, Args... >
    {
        using value_t = std::true_type;
        using type = Check<Args...>;
    };
}

// Type representing a missing type.
struct nonesuch
{
    nonesuch() = delete;
    ~nonesuch() = delete;
    nonesuch(nonesuch const&) = delete;
    void operator=(nonesuch const&) = delete;
};


template<   template< typename... > class Check,
            typename... Args
        >
using is_detected = typename internal::detect_impl< nonesuch, void, Check, Args... >::value_t;



// Our test
template< typename T >
using is_addable_impl = decltype( std::declval<T>() + std::declval<T>() );

template< typename T >
using is_addable = is_detected<is_addable_impl, T>;


auto main(int argc, const char* arv[])
    -> int
{
    std::cout   <<  std::boolalpha
                <<  is_addable<int>::value  << ", "
                <<  is_addable<nonesuch>::value << std::endl;
}
#include <iostream>
#include <type_traits>

struct X {};

template< typename T, typename = void >
struct is_addable
    : std::false_type
{};

 template< typename T >
 struct is_addable <T, std::void_t<decltype(std::declval<T>() + std::declval<T>())>>
     : std::true_type
 {};

int main()
{
    std::cout   <<  std::boolalpha 
                << is_addable<int>::value   << ", "
                << is_addable<X>::value
                << std::endl;
}
Z:\>cl /EHsc test.cxx
....
Z:\>test.exe
true, false
#include <type_traits>

template <typename...>
using void_t = void;

namespace internal
{
    template <typename V, typename D>
    struct detect_impl
    {
        using value_t = V;
        using type = D;
    };

    template <typename D, template <typename...> class Check, typename... Args>
    auto detect_check(char)
        -> detect_impl<std::false_type, D>;

    template <typename D, template <typename...> class Check, typename... Args>
    auto detect_check(int)
        -> decltype(void_t<Check<Args...>>(),
                    detect_impl<std::true_type, Check<Args...>>{});

    template <typename D, typename Void, template <typename...> class Check, typename... Args>
    struct detect : decltype(detect_check<D, Check, Args...>(0)) {};
}

struct nonesuch
{
    nonesuch() = delete;
    ~nonesuch() = delete;
    nonesuch(nonesuch const&) = delete;
    void operator=(nonesuch const&) = delete;
};

template <template< typename... > class Check, typename... Args>
using is_detected = typename internal::detect<nonesuch, void, Check, Args...>::value_t;