视图和跨步视图以及const噩梦的功能模板专业化

时间:2017-05-25 22:02:04

标签: c++ templates const c++17 array-view

我定义了一个类array_view和一个类strided_view(想想array_view和strided_array_view http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0122r0.pdf),我想专注于我可以迭代它以提高效率的方式 假设我有一个函数调度程序,它试图专门研究不同的情况。

让我们从一些简单的代码开始

template <class T>
    class view
    {};
template <class T>
    class sview
    {};
template<typename T1, typename T2, template <typename> class View1,   template <typename> class View2>
void PixelWiseUnary(const View1<T1>& i_vin, View2<T2>& o_vout)
{       
    PixelWiseUnaryDispatch<T1, T2, View1, View2> dispatcher;
    dispatcher(i_vin, o_vout);
}

然后我定义了不同的专业化

// primary use strided view 
template<typename T1, typename T2, template <typename> class View1, template <typename> class View2, typename = void>
struct PixelWiseUnaryDispatch
{
    void operator()(const View1<T1>& i_vin, View2<T2>& o_vout) const
    {
        std::cout << "***************" << std::endl;
        std::cout << "primary template" << std::endl;
        std::cout << "***************" << std::endl;

    }
};

template<typename T1, typename T2, template <typename> class View1, template <typename> class View2>
struct PixelWiseUnaryDispatch<T1,T2, View1, View2,
    std::enable_if_t<(!std::is_same_v<T1,T2> && std::is_same_v<View1<T1>,view<T1>> )&& std::is_same_v<View2<T2>, view<T2>>>
>
{
    void operator()(const View1<T1>& i_vin, View2<T2>& o_vout) const
    {
        std::cout << "***************" << std::endl;
        std::cout << "both view != type" << std::endl;
        std::cout << "***************" << std::endl;

    }
};

template<typename T,template <typename> class View1, template <typename> class View2>
struct PixelWiseUnaryDispatch<T,T, View1, View2,
    std::enable_if_t<(std::is_arithmetic_v<T> && std::is_same_v<View1<T>, view<T>>) && std::is_same_v<View2<T>, view<T>>>
>
{
    void operator()(const View1<T>& i_vin, View2<T>& o_vout) const
    {
        std::cout << "***************" << std::endl;
        std::cout << "both view same type" << std::endl;
        std::cout << "***************" << std::endl;

    }
};

然后定义一个简单的主

void main(void)
{
view<int> vin;
view<float> vinf;
view<int> vout;
sview<int> vsout;
PixelWiseUnary(vin, vsout); //primary template
PixelWiseUnary(vinf, vout); //both view != type
PixelWiseUnary(vin, vout);  //both view same type 
}

一切都很好并正确切换

但是当我尝试使用const时,事情变得奇怪了 例如

void main(void)
{
view<const int> vin;
view<const float> vinf;
view<int> vout;
sview<int> vsout;
PixelWiseUnary(vin, vsout); //primary template as expected
PixelWiseUnary(vinf, vout); //both view != type WTF i don't provide specialisation for const (cf https://stackoverflow.com/questions/14926482/const-and-non-const-template-specialization) so i expected primary template
PixelWiseUnary(vin, vout); //both view != type WTF i don't provide specialisation for const and i loose the same type specialization
}
}

我尝试添加来自Const and non const template specialization的建议,但在我的情况下它没有任何改变。

我缺少什么? 此致

注意:我使用最新的Visual2017社区版

1 个答案:

答案 0 :(得分:1)

我想你可以解决问题 (1)针对!std::is_same_v<T1 const, T2 const>案例测试T1(而不是测试T2"both view != type"是否属于同一类型) (2)在T1中使用T2T(而不是"both view same type")并添加测试std::is_same_v<T1 const, T2 const>

我的意思是(我只有一个C ++ 14编译器,因此我使用std::is_same<>::value而不是std::is_same_v<>

template <typename T1, typename T2,
          template <typename> class View1,
          template <typename> class View2>
struct PixelWiseUnaryDispatch <T1, T2, View1, View2,
   std::enable_if_t<
         !std::is_same<T1 const, T2 const>::value
      && std::is_same<View1<T1>, view<T1>>::value
      && std::is_same<View2<T2>, view<T2>>::value>
>
 {
   void operator()(View1<T1> const & i_vin, View2<T2> & o_vout) const
    {
      std::cout << "***************" << std::endl;
      std::cout << "both view != type" << std::endl;
      std::cout << "***************" << std::endl;
    }
 };

template <typename T1, typename T2, template <typename> class View1,
          template <typename> class View2>
struct PixelWiseUnaryDispatch<T1, T2, View1, View2,
   std::enable_if_t<
         std::is_same<T1 const, T2 const>::value
      && std::is_arithmetic<T1>::value
      && std::is_same<View1<T1>, view<T1>>::value
      && std::is_same<View2<T2>, view<T2>>::value>
>
 {
   void operator()(View1<T1> const & i_vin, View2<T2> & o_vout) const
    {
      std::cout << "***************" << std::endl;
      std::cout << "both view same type" << std::endl;
      std::cout << "***************" << std::endl;

    }
 };

En passant:{而不是强加View1<T1>View2<T2>view<T1>view<T2>的类型相同,您可以(在您的专业化中)避免使用{ {1}}和View1并直接使用View2

您可以按如下方式简化您的专业化

view