Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to override a template method matching only when two template parameters are the same?

Tags:

c++

templates

I have a function call:

template <typename A, typename B> bool foo();

I would like to override it so that any calls where A and B are the same type go to a special function override. I'm thinking of something like:

template<typename A>
    bool foo<A,A>() 
      { return false; }

However, this code does not compile, and I can't find any code that might work. My recourse so far has been to explicitly override all possible types:

template<> bool foo<class1,class1>() { return false; }
template<> bool foo<class2,class2>() { return false; }
template<> bool foo<class3,class3>() { return false; }

but this is inelegant and requires maintenance when new classes are brought in.

Thanks for any thoughts.

Edit: To be clear, when A is not the same type as B, I have code like this:

 template<typename A, typename B> 
 bool foo() {
    Thing<A,B> instance;  // Thing<A,A> is never legal and will not compile
 }

(The code gets called because I'm trying all possible combinations of B against A and vice-versa. I was hoping to deal with this easily with the compiler, rather than implement if-then tests on every B to make sure it doesn't match A. Maybe there's a better way of doing this, but I thought this design would be elegant.)

like image 394
Nathaniel Tagg Avatar asked Dec 03 '22 18:12

Nathaniel Tagg


2 Answers

Your attempt does not compile because partial function template specialization (template<typename A> bool foo<A,A>()) is not allowed. The usual workaround is to use overloading, as template parameters often occur as function parameters. In your case (no function parameters), if C++17 is available, you can use if constexpr together with the <type_traits> header, e.g.

#include <type_traits>

template <typename A, typename B> bool foo()
{
   if constexpr (std::is_same_v<A, B>)
      return true;
   else
      return false;
}
like image 82
lubgr Avatar answered Dec 28 '22 22:12

lubgr


If you don't have access to C++17 and if constexpr, you can simply use standard SFINAE:

#include <type_traits>

template <typename A, typename B, std::enable_if_t<!std::is_same<A, B>{}, int> = 0> 
bool foo() { return true; }

template <typename A, typename B, std::enable_if_t<std::is_same<A, B>{}, int> = 0> 
bool foo() { return false; }
like image 41
Holt Avatar answered Dec 28 '22 23:12

Holt