使用SFINAE检测相同的类继承 [英] Detect same class inheritance with SFINAE
问题描述
我试图写一个元函数,检查作为一个可变参数传递的所有类型是否不同。似乎最好的方法是从一组类继承并检测是否有错误。
问题是编译失败
编辑。问题不是如何写的元功能,而是怎么做我发现双继承错误和输出 false_type
时发生。 AFAIK,只能使用SFINAE。 template< typename T&
struct dummy {};
//错误:重复基本类型'dummy< int>'无效
template< typename T,typename U>
struct fail:dummy< T>,dummy< U> {};
template< typename T>
true_type test(fail< T,T> a = fail< T,T&
false_type test(...);
int main(){
cout<< decltype(test< int>()):: value<< endl;
}
编辑。 我们试图用专业化失败做到这一点,但是它没有工作与编译错误。 template<类型名T>
struct dummy {};
template< typename T,typename U>
struct fail:dummy< T>,dummy< U>,true_type {};
template< typename T,typename U = void>
struct test:false_type {};
template< typename T>
struct test< T,typename enable_if< fail< T,T> :: value,void> :: type& :true_type {};
您不能使用SFINAE捕获重复继承,因为它不是列出的14.8.2p8 [temp.deduct] 之下的扣除原因;同样,这是因为错误发生在模板扣除的直接上下文之外,因为它是你的 struct fail
的实例化 。
然而,有一种非常类似的技术适用于您的情况,即检测来自派生类的模糊转换到多个基类。显然,模糊的基类不能直接从单个派生类继承,但它可以在线性链中继承它们:
C<> A< int>
| /
C< int> A< char>
| /
C< char,int> A< int>
| /
C< int,char,int>
现在转换 C
A< int>
将是不明确的,并且作为模糊转换在14.8.2p8下列出,我们可以使用SFINAE来检测它:
#include< type_traits>
template< class> struct A {};
template< class ... Ts> struct C;
模板<> struct C<> {};
template< class T,class ... Ts>结构C< T,Ts ...> ;:A T,C< Ts ...> {};
template< class ... Ts> void f(A template< class ... Ts> std :: false_type g(...);
template< class ... Ts> (...),std :: true_type())g(int); ...,declare(f((A Ts(),C Ts ...
template< class ... Ts> using distinct = decltype(g< Ts ...>(0));
static_assert(distinct< int,char,float> :: value,!!);
static_assert(!distinct< int,char,int> :: value,!!);
I'm trying to write a metafunction that checks whether all types passed as a variadic template parameter are distinct. It seems that the most performant way to do this is to inherit from a set of classes and detect, whether there is an error.
The problem is that compilation fails in the following code, while I would expect SFINAE to work.
Edit. The question is not "how to write that metafunction" but "how do I catch that double inheritance error and output false_type
when it happens". AFAIK, it's possible only with SFINAE.
template <typename T>
struct dummy {};
// error: duplicate base type ‘dummy<int>’ invalid
template <typename T, typename U>
struct fail : dummy<T>, dummy<U> {};
template <typename T>
true_type test(fail<T, T> a = fail<T, T>());
false_type test(...);
int main() {
cout << decltype(test<int>())::value << endl;
}
Edit. Previously I've tried to do this with specialization failure, but it didn't work either with the same compilation error.
template <typename T>
struct dummy {};
template <typename T, typename U>
struct fail : dummy<T>, dummy<U>, true_type {};
template <typename T, typename U = void>
struct test : false_type {};
template <typename T>
struct test<T, typename enable_if<fail<T, T>::value, void>::type> : true_type {};
You can't catch duplicate inheritance with SFINAE, because it is not one of the listed reasons for deduction to fail under 14.8.2p8 [temp.deduct]; equally, it is because the error occurs outside the "immediate context" of template deduction, as it is an error with the instantiation of your struct fail
.
There is however a very similar technique which is suitable for use in your case, which is to detect an ambiguous conversion from a derived class to multiple base classes. Clearly the ambiguous base classes can't be inherited directly from a single derived class, but it works fine to inherit them in a linear chain:
C<> A<int>
| /
C<int> A<char>
| /
C<char, int> A<int>
| /
C<int, char, int>
Now a conversion from C<int, char, int>
to A<int>
will be ambiguous, and as ambiguous conversion is listed under 14.8.2p8 we can use SFINAE to detect it:
#include <type_traits>
template<class> struct A {};
template<class... Ts> struct C;
template<> struct C<> {};
template<class T, class... Ts> struct C<T, Ts...>: A<T>, C<Ts...> {};
template<class... Ts> void f(A<Ts>...);
template<class... Ts> std::false_type g(...);
template<class... Ts> decltype(f((A<Ts>(), C<Ts...>())...), std::true_type()) g(int);
template<class... Ts> using distinct = decltype(g<Ts...>(0));
static_assert(distinct<int, char, float>::value, "!!");
static_assert(!distinct<int, char, int>::value, "!!");
这篇关于使用SFINAE检测相同的类继承的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!