Reputation: 15327
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
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
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
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
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