Reputation: 2359
Based on the following templated struct, used as pixel accessor.
template<class T, std::size_t N>
struct PixelAccessor
{
T ch[N];
};
using pxUChar_C1 = PixelAccessor<unsigned char, 1>;
using pxUChar_C3 = PixelAccessor<unsigned char, 3>;
using pxUChar_C4 = PixelAccessor<unsigned char, 4>;
using pxFloat_C1 = PixelAccessor<float, 1>;
using pxFloat_C3 = PixelAccessor<float, 3>;
using pxFloat_C4 = PixelAccessor<float, 4>;
// etc. for all other types (int, short, ushort, ...)
I made the following function to work only with uchar and float pixel that are 3 channels.
template<typename T, typename = typename std::enable_if<std::is_same<T, pxUChar_C3>::value || std::is_same<T, pxFloat_C3>::value>::type>
bool function(Image img) {
// where getData is uchar*, and cast to T** allow 2D accessing
auto imgPtr = (T**)img->getData();
}
Is there a way to do the following, or anything similar ? I would like to enable all 3 channels pixel, what ever there type is ?
template<typename T, typename = typename std::enable_if<std::is_base_of< PixelAcessor<std::any, 3>,T>::value>::type>
I would like to have a C++11 solution, but if there is a need of a newer compiler, Im open to solution and see what I do.
Upvotes: 1
Views: 90
Reputation: 2359
As pointed in the comments, the usage of a wildcard such as std::any
is not possible in template.
But after discussion, the usage of the template like I asked was a bit foolish, since I want to always use the T as a PixelAccessor itself, so it possible to use it differently such as I only template the T for the PixelAccessor itself.
template<typename T, typename = typename std::enable_if<std::is_arithmetic<T>::value>::type>
bool function(Image img) {
// Sanity check
if(img->getNbChannels() != 3) return false;
// where getData is uchar*, and cast to T** allow 2D accessing
auto imgPtr = (PixelAccessor<T, 3>**)img->getData();
}
Upvotes: 0
Reputation: 181068
To get the function to take any PixelAccessor
where N
is 3
then you don't need enable_if
and SFINAE. Just using
template<typename T>
return_type function_name(PixelAccessor<T, 3> parameter_name)
{
// stuff
}
will give you a function that takes a PixelAccessor
of any type and has a size of 3.
Upvotes: 5
Reputation: 170289
You can use a custom channel extraction meta-function:
template<typename> struct GetPixelAccessorChannel
{ static constexpr std::size_t value = 0; };
template<typename T, std::size_t N> struct GetPixelAccessorChannel<PixelAccessor<T, N>>
{ static constexpr std::size_t value = N; };
Now it's a simple matter of testing the proper condition in the enable_if
:
template<typename T, typename = typename std::enable_if<GetPixelAccessorChannel<T>::value == 3>::type>
bool function();
And as an aside, I'd rethink (T**)img->getData()
in your stead. Needing such a cast looks very fishy to me.
Upvotes: 1