如果需要参数包,则使用SFINAE进行特殊化 [英] Specializing class with SFINAE if a parameter pack is needed

查看:63
本文介绍了如果需要参数包,则使用SFINAE进行特殊化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我对这个问题有了一个完美的答案时:
使用SFINAE进行专业培训的班级

As I got a perfect answer for the question: Specializing class with SFINAE

为完整起见,我在此处再次插入正确的解决方案作为示例:

For completeness I insert the correct solution as example here again:

class AA { public: using TRAIT = int; };
class BB { public: using TRAIT = float; };

template < typename T, typename UNUSED = void> class X;

template < typename T >
class X<T, typename std::enable_if< std::is_same< int, typename T::TRAIT>::value, void >::type>
{
    public: 
        X() { std::cout << "First" << std::endl; }
};

template < typename T > 
class X<T, typename std::enable_if< !std::is_same< int, typename T::TRAIT>::value, void >::type>
{   
    public:
        X() { std::cout << "Second" << std::endl; }
};

int main()
{
     X<AA> a;
     X<BB> b;
}

但是如果我必须使用参数包进行进一步使用,我看不到有机会写下这样的东西:

But if I have to use a parameter pack for further use, I see no chance to write the things down like:

template < typename T, typename ...S, typename UNUSED = void> class X;




错误:参数包 S必须位于模板参数列表

error: parameter pack 'S' must be at the end of the template parameter list

以不同的顺序定义

template < typename T, typename UNUSED = void, typename ...S> class X;

如果使用第一种其他类型,则会出现问题。

ends up in problems if the first additional type is in use.

好的,我所描述的是我实际上找不到的技术解决方案。也许有另外一种。我的基本问题是什么:该类需要2个不同的构造函数,这些构造函数调用不同的基类构造函数。但是,因为两个构造函数都具有相同的参数集,所以我没有机会专门化构造函数本身。

OK, what I describe is a technical solution which I can't find actually. Maybe there is a different one. What is my underlying problem: I need 2 different constructors for the class which call different base class constructors. But because both constructors have the same set of parameters I see no chance to specialize the constructors itself.

如果专门化构造函数可以工作,则可能是这样的:

If specialize constructors can work, it can be something like that:

template < typename T>
class Y
{
    public:
        template <typename U = T, typename V= typename std::enable_if< std::is_same< int, typename U::TRAIT>::value, int >::type>
            Y( const V* =nullptr) { std::cout << "First" << std::endl; }

        template <typename U = T, typename V= typename std::enable_if< !std::is_same< int, typename U::TRAIT>::value, float >::type>
            Y( const V* =nullptr) { std::cout << "Second" << std::endl; }

};


错误:'模板Y :: Y(const V *)'无法重载

error: 'template template Y::Y(const V*)' cannot be overloaded

但是如上所述。 ..我不知道是否可以做到这一点。

But as already mentioned... I have no idea if that can be done.

为了显示潜在的问题,我将给出以下示例,该示例显示了依赖于基类构造函数的不同用法

To show the underlying problem, I would give the following example which shows the different use of base class constructors dependent on a trait which is defined in the base class.

template <typename T, typename ... S>: public T
class Z
{
    public:
        // should work if T defines a trait
        Z( typename T::SomeType t): T( t ) {}
        // should be used if T defines another trait
        Z( typename T::SomeType t): T( )   {}
};


推荐答案

代替

template < typename T, typename ...S, typename UNUSED = void> class X;

您可以添加一层:

template <typename T, typename Dummy = void, typename ... Ts> class X_impl {};

然后

template <typename T, typename ...Ts>
using X = X_impl<T, void, Ts...>;

对于SFINAE,因为默认模板参数不是签名的一部分,

For SFINAE, as default template parameter is not part of signature,

template <typename U = T,
          typename V = std::enable_if_t<std::is_same<int, typename U::TRAIT>::value, int>>
 Y(const V* = nullptr) { std::cout << "First" << std::endl; }

template <typename U = T,
          typename V = std::enable_if_t<!std::is_same<int,
                                                      typename U::TRAIT>::value, float>>
Y(const V* = nullptr) { std::cout << "Second" << std::endl; }

应重写,例如:

template <typename U = T,
          std::enable_if_t<std::is_same<int, typename U::TRAIT>::value>* = nullptr>
 Y() { std::cout << "First" << std::endl; }

template <typename U = T,
          std::enable_if_t<!std::is_same<int, typename U::TRAIT>::value>* = nullptr>
Y() { std::cout << "Second" << std::endl; }

这篇关于如果需要参数包,则使用SFINAE进行特殊化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆