传递模板实例化

时间:2015-06-22 10:16:01

标签: c++ templates template-specialization transitivity

我有一个转换模板,如果转换是安全的,应该在指向类型的指针之间进行转换。这类似于static_cast,但允许用户定义的类型。

示例:复杂类型的2个表示,一个作为结构,具有2个实数/图像成员,一个作为具有2个元素的数组。将指向其中一个的指针转换为指向另一个的指针是安全的。

我的模板如下所示:

template< typename T_Src, typename T_Dest, typename T_SFINAE = void >
struct SafePtrCast;

template< typename T >
struct SafePtrCast< Complex<T>*, T* >
{
    T*
    operator()(Complex<T>* data)
    {
        return &data->real;
    }
};

template< typename T >
struct SafePtrCast< T*, fftw_complex* >
    :Ptr2Ptr<T, fftw_complex>{};

template< typename T_Src, typename T_Dest = T_Src >
struct Ptr2Ptr
{
    using Src = T_Src;
    using Dest = T_Dest;

    Dest*
    operator()(Src* data) const
    {
        return reinterpret_cast<Dest*>(data);
    }
};

也就是说,我可以从Complex *转换为T *,从T *转换为fftw_complex *。从语义上讲,这意味着我也可以从Complex *转换为fftw_complex *。

但我怎么能告诉编译器,这没关系?我尝试过:

template< typename T_Src, typename T_Dest >
struct SafePtrCast<
    T_Src,
    T_Dest,
    void_t< std::result_of_t<
        SafePtrCast<
            std::result_of_t<
                SafePtrCast<T_Src, double* >
            >,
            T_Dest
        >
    > >
>{
    using Conv1 = SafePtrCast< T_Src, double* >;
    using Conv2 = SafePtrCast< double*, T_Dest >;

    T_Dest
    operator()(T_Src&& data) const
    {
        return Conv2(Conv1(std::forward<T_Src>(data)));
    }
};

并使用它与几个基本类型(double,float,int ...),以允许至少T-> base-> U,这应该足够了。

不幸的是,编译器似乎没有找到SafePtrCast&lt;的特化。复杂,fftw_complex &gt;

有没有更好的方法来解决这个问题?我的模板怎么了?

1 个答案:

答案 0 :(得分:0)

使用特质怎么样:

template< typename T_Src, typename T_Dest, bool  >
struct Ptr2Ptr

// allowed conversion
template< typename T_Src, typename T_Dest>
struct Ptr2Ptr<T_Src, T_Dest, true>
{
    using Src = T_Src;
    using Dest = T_Dest;

    static Dest* conv(Src* data) const
    {
        return reinterpret_cast<Dest*>(data);
    }
};

template <typename T_Src, typename T_Dest>
conv_trait
{
    static const bool enabled = false ;
}
template< typename T_Src, typename T_Dest>
struct SafePtrCast
{
    T_Dest*
    operator()(T_Src* data) const
    {
        return Ptr2Ptr<T_Src, T_Dest, conv_trait<T_Src, T_Dest>::value>::conv(data);
    }
}

现在,您可以将conv_trais专门用于允许的转化

template <class T>
conv_trait<Complex, T *>
{
    static const bool value = true ;
}