检查类型是否在C ++

时间:2018-01-06 23:22:10

标签: c++ templates template-meta-programming

我正在编写一个构造函数,并且希望为任何为整数参数实现[][]的类型定义它。换句话说,T类型必须定义T[],并且在[]上使用T时返回的类型也会定义[],例如,{ {1}}被调用。

我知道如何使用回答here检查是否存在重载运算符,该回答显示T[2][3]的方法,可以很容易地扩展到我的情况。

但问题是,我想检查operator==的类型是否还有T[]

如上所述,我还需要检查重载的operator[]接受的参数是否包含任何整数类型,因此operator[]会有一些operator[](const T& i),这会产生T真。

显然,我的目的是允许接口接受表现的任何内容,就像使用标准方法访问其元素的矩阵一样。

2 个答案:

答案 0 :(得分:2)

你可以这样做在std::declval<const T>()[1][1]

template<class T, class = decltype(std::declval<const T&>()[1][1])>
void foo(const T& matrix){
    ...
}

或:

template<class T, decltype(void(std::declval<const T&>()[1][1]),true)=true>
void foo(const T& matrix){
  ...
}

如果您有多个SFINAE选择foo重载,效果会更好。

*)我在手机上,所以我没有用编译器检查过这个。

答案 1 :(得分:2)

以下是两种方法。第一个不使用任何外部库,并使用与您发布的链接答案相同的想法。第二个使用boost.hana库中的功能。

#include <iostream>
#include <type_traits>
#include <vector>
#include <boost/hana/type.hpp>

// SFINAE trick, not using any external libraries
template <class X>
class check {

    // this overload will be selected whenever X[][] is defined
    template <class T>
    static auto call(T*) -> decltype(std::declval<T>()[1][1], std::true_type{});

    // and this when X[][] is not defined
    template <class T>
    static std::false_type call(...);

public:

    using type = decltype (call<X>(0));
};

// using boost.hana library
template <class X>
class hana_check {

    static auto call() {
        auto test = boost::hana::is_valid([](auto&& x) -> decltype (x[1][1]) {});
        return decltype(test(std::declval<X>())){};
    }

public:

    using type = decltype (call());
};

using test_type1 = check<int>::type; // false_type
using test_type2 = check<std::vector<std::vector<int>>>::type; // true_type
using test_type3 = hana_check<double>::type; // false_type
using test_type4 = hana_check<std::vector<std::vector<double>>>::type; // true_type

int main() {

    std::cout << test_type1::value << std::endl;
    std::cout << test_type2::value << std::endl;
    std::cout << test_type3::value << std::endl;
    std::cout << test_type4::value << std::endl;
}