我想使用标准代码编写像std::is_union这样的工具,我们知道类类型不能扩展并集类型,这是错误的,所以一些类似这样的代码

#include <iostream>
template<typename T>
class class_type_can_extends :public T{
public:
    using type = void;
};

template<typename T,typename U = void>
struct is_not_union:std::false_type {

};

template<typename T>
struct is_not_union < T, std::void_t<typename class_type_can_extends <T>::type >> :std::true_type {

};

class c_data{

};
union u_data{
};

int main(){
 /*#1*/  std::cout<< is_not_union<c_data>::value<<std::endl; /*print true*/
 /*#2*/  std::cout<< is_not_union<u_data>::value<<std::endl; /*this code make
         all complier error*/
}

g++打印错误:
main.cpp: In instantiation of ‘class class_type_can_extends<u_data>’:
main.cpp:26:43:   recursively required by substitution of ‘template<class T> struct is_not_union<T, std::void_t<typename class_type_can_extends<T>::type> > [with T = u_data]’
main.cpp:26:43:   required from here
main.cpp:3:7: error: base type ‘u_data’ fails to be a struct or class type
 class class_type_can_extends :public T {

lang打印错误:
main.cpp:3:38: error: unions cannot be base classes
class class_type_can_extends :public T {
                              ~~~~~~~^
main.cpp:14:47: note: in instantiation of template class 'class_type_can_extends<u_data>' requested here
struct is_not_union < T, std::void_t<typename class_type_can_extends <T>::type >> :std::true_type {
                                              ^
main.cpp:26:23: note: during template argument deduction for class template partial specialization 'is_not_union<T,
      std::void_t<typename class_type_can_extends<T>::type> >' [with T = u_data]
        /*#2*/  std::cout << is_not_union<u_data>::value << std::endl; /*this code make
                             ^
main.cpp:26:23: note: in instantiation of template class 'is_not_union<u_data, void>' requested here
1 error generated.

vs:



为什么#2代码使编译器出错,编译器将对#2代码使用SFINAE规则(用“u_data”替换T,然后失败),然后选择主模板?为什么sfinae在这里无效,这可能是一个错误?

最佳答案

cppreference:



SFINAE适用于即时上下文,这里您将遇到严重的错误失败。

typename class_type_can_extends<T>::type中,如果type不存在,则应用SFINAE,如果class_type_can_extends<T>的实例化失败,则不应用SFINAE。

注意,我们不能仅使用标准C++来区分union和类类型
(无std::is_union)。大多数编译器为此提供内在函数。

关于c++ - 使用模板时可能是编译器中的SFINAE BUG?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/58386940/

10-12 13:08