Специализация шаблонов функций как для просмотра вида, так и для постепенного просмотра и постоянного кошмара

Я определяю класс 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
}
}

Я пытаюсь добавить совет от Константная и неконстантная специализация шаблонов но это ничего не меняет в моем случае.

Что мне не хватает?
С уважением

Примечание: я работаю с последней версией сообщества Visual2017

2

Решение

Я полагаю, вы можете решить проблему
(1) тестирование, которое !std::is_same_v<T1 const, T2 const> (вместо того, чтобы проверить это T1 а также T2 не тот же тип) для "both view != type" дело
(2) использовать T1 а также T2 (вместо T) в "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>, вы можете (в вашей специализации) избежать использования 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;

}
};
1

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector