Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Template function specialization for specific template ( not type )

I have some templated class types like A,B,C as follows:

template < typename T >
class A{}; 

template < typename T >
class B{}; 

template < typename T >
class C{};

And now I want to have a function which accepts in general any type like:

template < typename T> 
void Func()
{
    std::cout << "Default " << __PRETTY_FUNCTION__ << std::endl;
}

And now I want to specialize the function to only accept one of the given template classes like:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

template < typename T>
void Func<A<T>>() 
{
    std::cout << "All A Types " << __PRETTY_FUNCTION__ << std::endl;
}

Which is not allowed because it is only a partial specialization. OK.

I think concept may help but it feels that I think much too complicated. My solution is:

template < typename T, template <typename > typename OUTER >
bool Check; 

template < typename INNER, template < typename > typename OUTER, template < typename> typename T>
constexpr bool Check< T<INNER>, OUTER > = std::is_same_v< OUTER<INNER>, T<INNER>>;

template < typename T >
concept IsA = Check< T, A >; 

template < typename T >
concept IsB = Check< T, B >; 


template < IsA T >
void Func()
{
    std::cout << "All A Types " <<   __PRETTY_FUNCTION__ << std::endl;
}

template < IsB T >
void Func()
{
    std::cout << "All B Types " <<   __PRETTY_FUNCTION__ << std::endl;
}

int main()
{
    Func<A<int>>();
    Func<B<int>>();
    Func<C<int>>();
}

It feels a bit complicated to me. Can that be simplified? Would be nice if the Check template can be removed. Any idea?

See full example here live

>Solution :

OP writes:

Yes, would be nice to write some "instant" code directly in the functions template parameter… if possible…

Normally, to determine whether it’s a specialization of some given class template, we define a trait ahead of time and then check whether the type satisfies that trait. If you don’t want to define anything ahead of time, you have to find a way to perform template argument deduction inline, so you can check whether it succeeds. In C++20, this is straightforward but a bit ugly:

template <typename T> 
void Func()
{
    std::cout << "unconstrained" << std::endl;
}

template <typename T>
requires requires {
    []<typename U>(const A<U>&){}(std::declval<T>());
}
void Func()
{
    std::cout << "constrained" << std::endl;
}

Here, the requires-clause checks whether T can be bound to an argument of type const A<U>& for some deducible U. You can see this example here: https://godbolt.org/z/dTEbaaPvh

This isn’t exactly pleasant to read. If you will be using this hack multiple times, I think it’s better to just define traits instead. I’ve answered your question simply to satisfy your curiosity, not to recommend this technique.

The version above will pick the constrained version not only when the template argument is some A<U> but also when it is possibly cv-qualified, possibly ref-qualified, and possibly publicly derived from A<U>. Some tweaks are possible to make the constraint more strict.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading