kfmfe04
kfmfe04

Reputation: 15327

How to check if two template parameters are exactly the same?

How do I modify the following function template so that it returns 42 if template parameters T and U are exactly the same type?

template<typename T,typename U>
int Foo()
{
  return 0;
}

Upvotes: 8

Views: 5063

Answers (4)

GManNickG
GManNickG

Reputation: 503855

Just for completeness in the answers, here's how you can make this choice at compile-time without classes:

namespace detail
{
    int Foo(std::true_type)
    {
        return 42;
    }

    int Foo(std::false_type)
    {
        return 0;
    }
}

template <typename T, typename U>
int Foo()
{
    return detail::Foo(std::is_same<T, U>());
}

This compile-time branching is important when the two different code paths have different requirements on your arguments (none in this case, though). For example, in one path you use member function x() and in the other y(); or as you've noted, even entirely "different" functions.

This, to me, is much simpler than managing a class.

Upvotes: 4

TemplateRex
TemplateRex

Reputation: 70526

An idiomatic way is to delegate the work to a helper function object in a detail namespace that you can partially specialize for the case where T is the same as U (or for any other compile-time pattern that you can use in class templates).

namespace detail {

template<typename T, typename U>
struct foo
{
     int operator()() const
     {
         return 0;
     }
};

template<typename T>
struct foo<T, T>
{
     int operator()() const
     {
         return 42;
     }
};

} // namespace detail 

template<typename T, typename U>
int Foo()
{
     return detail::foo<T, U>()();
}

For functions which also have deducible arguments (e.g. a Foo(T x, U y) would) this combines the power of argument deduction of function templates, and the specialization capabilities of class templates, without users every being the wiser (well, you need the convention that they do not call anything from namespace detail directly)

Upvotes: 7

Alex Chamberlain
Alex Chamberlain

Reputation: 4207

What about this?

#include <iostream>

template<typename T,typename U>
struct Foo {
  int operator()()
  {
    return 0;
  }
};

template<typename T>
struct Foo<T, T> {
  int operator()()
  {
    return 42;
  }
};

int main() {
   std::cout << Foo<int, int>()() << std::endl;
   std::cout << Foo<int, double>()() << std::endl;
}

Upvotes: 1

hmjd
hmjd

Reputation: 121971

Using std::is_same can provide the desired behaviour:

#include <type_traits>

template<typename T,typename U>
int Foo()
{
    return std::is_same<T, U>::value ? 42 : 0;
}

Upvotes: 15

Related Questions