在通用 lambda 中使用 constexpr-if 来确定参数的类型
Using constexpr-if in a generic lambda to determine type of a parameter
我有以下问题:我有一个 class 层次结构,其中有一个基础 class 和两个子 class 。我已经实现了一个 resolve_type
函数,它接受基 class 的实例和一个通用的 lambda(或类似的)。该函数解析其类型并将其传递给 lambda。在这个 lambda 表达式中,我想在 constexpr-if 条件下检查列的类型,以排除某些类型。我曾尝试在 sub-classes 中使用 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 库,所以解决方案也可以使用这两个。有人有什么想法吗?
改用 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{});
}
或者使用中间 class 模板而不是连续重新定义 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{});
}
有很多选择,但您不能仅仅因为将其声明为 const
引用就在常量表达式中使用 col
。 col
是类型 T
的运行时实例,您不可能像您尝试的那样在编译时使用它。
我认为你想多了。您不需要成员函数来识别对象的类型。你可以只看类型。所以一开始,这很简单:
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) {
}));
我有以下问题:我有一个 class 层次结构,其中有一个基础 class 和两个子 class 。我已经实现了一个 resolve_type
函数,它接受基 class 的实例和一个通用的 lambda(或类似的)。该函数解析其类型并将其传递给 lambda。在这个 lambda 表达式中,我想在 constexpr-if 条件下检查列的类型,以排除某些类型。我曾尝试在 sub-classes 中使用 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 库,所以解决方案也可以使用这两个。有人有什么想法吗?
改用 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{});
}
或者使用中间 class 模板而不是连续重新定义 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{});
}
有很多选择,但您不能仅仅因为将其声明为 const
引用就在常量表达式中使用 col
。 col
是类型 T
的运行时实例,您不可能像您尝试的那样在编译时使用它。
我认为你想多了。您不需要成员函数来识别对象的类型。你可以只看类型。所以一开始,这很简单:
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) {
}));