简体   繁体   中英

May be a SFINAE BUG in complier when use template?

I want to use the standard code to write the utils like std::is_union,we know class type can not extends union type,it's error,so some code like these

#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++ print error:

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 { 

clang print error:

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:

error C2569

why #2 code make complier error,The complier would be using SFINAE rules on #2 code(substituted T by "u_data",then Failed ),and to chose primary template?why the sfinae not effective here,may be a bug here?

From cppreference :

Only the failures in the types and expressions in the immediate context of the function type or its template parameter types or its explicit specifier (since C++20) are SFINAE errors. If the evaluation of a substituted type/expression causes a side-effect such as instantiation of some template specialization, generation of an implicitly-defined member function, etc, errors in those side-effects are treated as hard errors

SFINAE applies on immediate context, here you have a hard error failure.

In typename class_type_can_extends<T>::type , SFINAE applies if type doesn't exist, not if instantiation of class_type_can_extends<T> fails.

Notice that we cannot distinguish between union and class types using only standard C++ (without std::is_union ). Most compilers provide intrinsics for that.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM