Reputation: 15294
I am making a function template:
template <typename T>
void foo (T arg1) {}
But I want to make sure T is deferencable to type Foo, so arg1
needs to be either:
Foo * //This case T = Foo*
Or
Any type X which implements `*` operator which returns a Foo/Foo&/Foo&&
So I need something like:
template <typename T>
void foo(T arg1, std::enable_if<std::is_same<typeid(*arg1), typeid(Foo)>::value> * = 0) {}
But this does not compile and complains:
typecheck.cpp:6:54: error: use of parameter âarg1â outside function body
void foo(T arg1, std::enable_if<std::is_same<typeid(*arg1), typeid(Foo)>::value> * = 0) {}
^
How can I achieve this?
Upvotes: 1
Views: 684
Reputation: 8824
You should prefer is_convertible instead of is_same to catch sub classes of Foo, the enable_if in the template argument list instead of the function arguments or return type is also easier to read.
template <typename T, typename = typename std::enable_if<std::is_convertible<decltype( *std::declval<T>() ), Foo>::value>::type >
void foo(T arg1);
less garbage in c++14 :
template <typename T, typename = std::enable_if_t<std::is_convertible<decltype( *std::declval<T>() ), Foo>::value> >
void foo(T arg1);
Upvotes: 7
Reputation:
A template is way too complicated:
void foo(Foo&);
void foo(const Foo&);
void foo(Foo*);
void foo(const Foo*);
and dispatch accordingly.
#include <iostream>
struct Foo {};
struct Any {
operator Foo () const { return Foo(); }
};
void foo(const Foo&) {
std::cout << "Hello Foo\n";
}
int main() {
Any a;
foo(a);
}
Upvotes: 0
Reputation: 110698
You want decltype
, not typeid
. You use typeid
to get run-time type information, whereas decltype
will give you the type of an expression at compile-time.
std::is_same<decltype(*arg1), Foo>::value
Note, if you don't need a call with a type that doesn't point at a Foo
to fall back to a different overload, then you might prefer to use static_assert
instead of std::enable_if
:
template <typename T>
void foo(T arg1) {
static_assert(std::is_same<decltype(*arg1), Foo>::value, "Performing indirection with an object of type T must give a Foo");
// ...
}
Upvotes: 3