Silly square
Silly square

Reputation: 57

How can we check the type of the template parameter in c++?

In java we can specify the type of the of the parameter

public <T extends SomeInterface> void genericMethod(Set<? extends T> tSet) {
    // Do something 
}

It is written as T extends SomeInterface. Is this feature supported by c++?

Upvotes: 3

Views: 82

Answers (2)

Jonas
Jonas

Reputation: 7017

It sounds to me like you want something like this:

template <class T>
std::enable_if_t<std::is_base_of<SomeInterface, T>::value, void>
genericMethod(std::set<T> tSet)
{
    // Do something
}

If you can elaborate on what Set<? extends T> tSet means, then I'm sure we can incorporate that as well.

Upvotes: 4

Curious
Curious

Reputation: 21540

You can do this one of two ways, the simplest solution here is to use a base class pointer that represents the interface. After that point you can only pass pointers to objects that are derived from that base class. So something like this

#include <iostream>
#include <string>

using std::cout;
using std::endl;

class BaseOne {};
class BaseTwo {};

class DerivedOne : public BaseOne {};
class DerivedTwo : public BaseTwo {};

void foo(BaseOne*) {
    cout << __PRETTY_FUNCTION__ << endl;
}
void foo(BaseTwo*) {
    cout << __PRETTY_FUNCTION__ << endl;
}

int main() {
    auto derived_one = DerivedOne{};
    auto derived_two = DerivedTwo{};
    foo(&derived_one);
    foo(&derived_two);
}

Or if the goal is to do this at compile time without base classes, i.e. without inheritance and without concepts (which are expected to come out in C++20 ¯\_(ツ)_/¯) and only check the presence of some methods, then you can do something like this

#include <iostream>
#include <type_traits>

using std::cout;
using std::endl;

struct One { void one() {} };

struct Two { void two() {} };

/**
 * Loose SFINAE based concepts
 */
template <typename Type, typename T = std::decay_t<Type>>
using EnableIfOne = std::enable_if_t<std::is_same<
        decltype(std::declval<T>().one()), decltype(std::declval<T>().one())>
    ::value>;
template <typename Type, typename T = std::decay_t<Type>>
using EnableIfTwo = std::enable_if_t<std::is_same<
        decltype(std::declval<T>().two()), decltype(std::declval<T>().two())>
    ::value>;

template <typename T, EnableIfOne<T>* = nullptr>
void foo(T&) {
    cout << __PRETTY_FUNCTION__ << endl;
}
template <typename T, EnableIfTwo<T>* = nullptr>
void foo(T&) {
    cout << __PRETTY_FUNCTION__ << endl;
}

int main() {
    auto one = One{};
    auto two = Two{};
    foo(one);
    foo(two);
}

Upvotes: 1

Related Questions