Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.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++ 无例外+;无法在MSVC下编译declval_C++_Templates_Visual C++_Compiler Errors_Sfinae - Fatal编程技术网

C++ 无例外+;无法在MSVC下编译declval

C++ 无例外+;无法在MSVC下编译declval,c++,templates,visual-c++,compiler-errors,sfinae,C++,Templates,Visual C++,Compiler Errors,Sfinae,我试图实现我对我的SO问题的答案: 我的目标是检测模板类T中是否存在void cancel()noexcept方法。 以下是我的最简单的例子: #include <iostream> #include <type_traits> template<class T, class = void> struct has_cancel : std::false_type {}; template<class T> struct has_cancel&l

我试图实现我对我的SO问题的答案: 我的目标是检测模板类
T
中是否存在
void cancel()noexcept
方法。 以下是我的最简单的例子:

#include <iostream>
#include <type_traits>

template<class T, class = void>
struct has_cancel : std::false_type {};

template<class T>
struct has_cancel<T,
    typename std::void_t<decltype(std::declval<T>().cancel()),
    typename std::enable_if_t<noexcept(std::declval<T>().cancel())>
    >
> : std::true_type {};

void print_has_cancel(std::true_type) {
    std::cout << "cancel found" << std::endl;
}

void print_has_cancel(std::false_type) {
    std::cout << "cancel not found" << std::endl;
}

struct A{

};

struct B {
    void cancel(){}
};

struct C {
    int cancel() noexcept {}
};

struct D{
    void cancel() noexcept {}
};

int main(){
    print_has_cancel(has_cancel<A>());
    print_has_cancel(has_cancel<B>());
    print_has_cancel(has_cancel<C>());
    print_has_cancel(has_cancel<D>());
    return 0;
}

#包括
#包括
模板
结构有_cancel:std::false_type{};
模板
结构有_cancel:std::true_type{};
作废打印已取消(标准::真打印类型){
std::cout C:\Users\David Haim\source\repos\cpp_sandbox\cpp_sandbox\cpp_sandbox.cpp(10,1):消息:类型为“\u添加\引用::\右值”
1> C:\Users\David Haim\source\repos\cpp_sandbox\cpp_sandbox\cpp_sandbox.cpp(10,19):错误C2056:非法表达式
1> 已完成构建项目“cpp_sandbox.vcxproj”--失败。
======生成:0成功,1失败,0最新,0跳过==========
经过一些研究,问题在于语法
noexcept(std::declval().something())
-MSVC拒绝理解这一行

1) MSVC为什么抱怨?是在代码中还是在编译器中


2) 我怎样才能让它继续编译呢?

MSVC的语法本身没有问题。它似乎只是假设SFINAE在这种情况下不适用,所以将
void
替换为type会产生错误。为什么或者标准中是否支持这一点,我现在不知道(但我对此表示怀疑)

通过将声明中的
noexcept
条件移动到
struct
的定义中,可以很容易地解决这个问题,这样,如果第一个
decltype
格式错误(即如果
.cancel()
根本不存在)并且SFINAE启动,它就永远不会被替换:

template<class T>
struct has_cancel<T,
    typename std::void_t<decltype(std::declval<T>().cancel())    >
> : std::bool_constant<noexcept(std::declval<T>().cancel())> {};
模板
结构有_cancel:std::bool_常量{};

我相信一些东西,但还没有在VS中实现。然而,旧的SIFANE技巧可能会有所帮助?请看@P0W,它不会检测
取消
是否不例外。我对任何版本的标准都很满意,只要这个技巧也能检测到不例外。我查了一下,发现这个:“直到CWG 1558(一个C++14缺陷),别名模板中未使用的参数不能保证确保SFINAE,可以忽略。@Frodyne这似乎不是MSVC所考虑的。即使删除了
void\t
,并且仅使用了一个简单的
enable\u if\t
,它仍然会产生相同的错误:
template<class T>
struct has_cancel<T,
    typename std::void_t<decltype(std::declval<T>().cancel())    >
> : std::bool_constant<noexcept(std::declval<T>().cancel())> {};