视图和跨步视图的函数模板专业化和 const 噩梦
Function template specialization for both view and strided view and const nightmare
我定义了一个classarray_view和一个classstrided_view(想想array_view和strided_array_viewhttp://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;
}
};
然后定义一个简单的main
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 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) 针对 "both view != type"
案例测试 !std::is_same_v<T1 const, T2 const>
(而不是测试 T1
和 T2
不是同一类型)
(2) 在 "both view same type"
中使用 T1
和 T2
(而不是 T
)并添加测试 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>
是同一类型,你可以(在你的专业中)避免使用View1
和 View2
并直接使用 view
。
您可以按如下方式简化您的专业化
template <typename T1, typename T2>
struct PixelWiseUnaryDispatch <T1, T2, view, view,
std::enable_if_t<!std::is_same<T1 const, T2 const>::value>>
{
void operator()(view<T1> const & i_vin, view<T2> & o_vout) const
{
std::cout << "***************" << std::endl;
std::cout << "both view != type" << std::endl;
std::cout << "***************" << std::endl;
}
};
template <typename T1, typename T2>
struct PixelWiseUnaryDispatch<T1, T2, view, view,
std::enable_if_t<
std::is_same<T1 const, T2 const>::value
&& std::is_arithmetic<T1>::value>>
{
void operator()(view<T1> const & i_vin, view<T2> & o_vout) const
{
std::cout << "***************" << std::endl;
std::cout << "both view same type" << std::endl;
std::cout << "***************" << std::endl;
}
};
我定义了一个classarray_view和一个classstrided_view(想想array_view和strided_array_viewhttp://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;
}
};
然后定义一个简单的main
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 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) 针对 "both view != type"
案例测试 !std::is_same_v<T1 const, T2 const>
(而不是测试 T1
和 T2
不是同一类型)
(2) 在 "both view same type"
中使用 T1
和 T2
(而不是 T
)并添加测试 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>
是同一类型,你可以(在你的专业中)避免使用View1
和 View2
并直接使用 view
。
您可以按如下方式简化您的专业化
template <typename T1, typename T2>
struct PixelWiseUnaryDispatch <T1, T2, view, view,
std::enable_if_t<!std::is_same<T1 const, T2 const>::value>>
{
void operator()(view<T1> const & i_vin, view<T2> & o_vout) const
{
std::cout << "***************" << std::endl;
std::cout << "both view != type" << std::endl;
std::cout << "***************" << std::endl;
}
};
template <typename T1, typename T2>
struct PixelWiseUnaryDispatch<T1, T2, view, view,
std::enable_if_t<
std::is_same<T1 const, T2 const>::value
&& std::is_arithmetic<T1>::value>>
{
void operator()(view<T1> const & i_vin, view<T2> & o_vout) const
{
std::cout << "***************" << std::endl;
std::cout << "both view same type" << std::endl;
std::cout << "***************" << std::endl;
}
};