2

我有以下问题:我有一个包含一个基类和两个子类的类层次结构。我已经实现了一个resolve_type接受基类实例和通用 lambda(或类似)的函数。该函数解析其类型并将其传递给 lambda。在这个 lambda 中,我想在 constexpr-if 条件下检查列的类型,以排除某些类型。我曾尝试使用子类中的 constexpr 成员函数来做到这一点,但不幸的是没有奏效。

代码:

class AbstractColumn
{
};

template <typename Type>
class DataColumn : public AbstractColumn
{
public:
    constexpr bool is_reference_column() { return false; }

    void foo() {}
};

class ReferenceColumn : public AbstractColumn
{
public:
    constexpr bool is_reference_column() { return true; }
};

template <typename Functor>
resolve_type(const AbstractColumn & col, const Functor & func);

用法:

AbstractColumn & col = ...;

...

resolve_type(col, [] (const auto & col)
{
    // col could be ReferenceColumn, DataColumn<int>, DataColumn<float>, DataColumn<double>, DataColumn<std::string> ...
    if constexpr (!col.is_reference_column()) {
        col.foo();
    }
});

编译器错误:

Apple LLVM version 8.1.0 (clang-802.0.42)
error: constexpr if condition is not a constant expression 
if constexpr (col.is_reference_column()) {

我知道我可以decltype用来获取类型,然后继续使用一些模板魔法,但我希望找到一些更具可读性的东西。我的项目已经使用了 boost 和它的 hana 库,所以解决方案也可以使用这两个。有没有人有任何想法?

4

2 回答 2

2

改用一种static constexpr方法。
它遵循一个最小的工作示例:

#include<type_traits>

struct A {
    static constexpr bool is_reference_column() { return false; }
};

int main() {
    [](const auto &col) {
        if constexpr(std::decay_t<decltype(col)>::is_reference_column()) {
            // ...
        }
    }(A{});
}

或者只是继承自std::true_type/ std::false_type

#include<type_traits>

struct A: std::true_type {};

int main() {
    [](const auto &col) {
        if constexpr(std::decay_t<decltype(col)>::value) {
            // ...
        }
    }(A{});
}

或者使用中间类模板而不是不断地重新定义is_reference_column

#include<type_traits>

template<bool refcol>
struct I {
    static constexpr bool is_reference_column = refcol;
};

struct A: I<true> {};

int main() {
    [](const auto &col) {
        if constexpr(std::decay_t<decltype(col)>::is_reference_column) {
            // ...
        }
    }(A{});
}

有很多选择,但你不能col仅仅因为你将它声明为const引用就简单地在常量表达式中使用。col是 type 的运行时实例,T你不可能像你试图做的那样在编译时使用它。

于 2017-07-22T20:04:26.983 回答
1

我觉得你想多了。您不需要成员函数来识别对象的类型。你可以只看类型。因此,首先,这很简单:

resolve_type(col, [] (const auto& col)
{
    if constexpr (hana::typeid_(col) == hana::type_c<ReferenceColumn>) {
        col.foo();
    }
});

更简单的方法是创建一个重载集并使用重载决议。这种机制有几种实现方式,用 C++17 编写特别简单。使用它:

resolve_type(col, overload(
    [](ReferenceColumn const& ref){
       ref.foo();
    },
    [](auto const& other) {
    }));
于 2017-07-22T23:36:48.887 回答