我们如何在c ++中检查模板参数的类型?

时间:2017-06-30 11:02:28

标签: c++

在java中,我们可以指定参数的类型

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

它写成T extends SomeInterface。这个功能是否受c ++支持?

2 个答案:

答案 0 :(得分:4)

听起来像你想要这样的东西:

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

如果您能详细说明Set<? extends T> tSet的含义,那么我相信我们也可以将其合并。

答案 1 :(得分:1)

您可以使用以下两种方法之一:这里最简单的解决方案是使用表示接口的基类指针。在此之后,您只能将指针传递给从该基类派生的对象。像这样的东西

#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);
}

或者如果目标是在没有基类的编译时执行此操作,即没有继承和没有概念(预计会出现在C ++ 20 \ _(ツ)_ /¯)并且只检查存在一些方法,那么你可以做这样的事情

#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);
}