Matching指向作为模板形参的成员及其类型的指针



给定以下代码

struct data {
int velocity;
};
template <typename Data>
class Collector {
// ...
public:
void add(const Data& data) {}
template <typename T>
T average1(T Data::*field) const {
return T{}; // Some calculation here
}
template <T Data::*field>
T average2() const {
return T{}; // Some calculation here
}
};
void foo() {
Collector<data> collector;
// I have no problem handling the average by sending member as parameter
auto ok = collector.average1(&data::velocity);
// But compilation here fails
auto error = collector.average2<&data::velocity>();
}

我的意图是通过模板参数替换传递成员指针到函数,但不能同时匹配成员类型和成员,我可以做一些像

template <typename T, T Data::*field>
T average2() const {
return T{}; // Some calculation here
}

但是我必须调用as

auto error = collector.average2<int, &data::velocity>();

,这是一个但丑陋的,似乎没有必要的

你知道如何解决这个问题或者有更好的方法来收集这类数据吗?

Thanks in advance

在c++ 17中,您可以通过将value template参数扩展为auto并在以后的行中解析T(例如decltype())来使模板化版本工作。

#include <type_traits>
template <typename Data>
class Collector {
// ...
public:
template <auto field>
auto average2() const {
using T = decltype(std::declval<Data>().*field);
return T{}; // Some calculation here
}
};
void foo() {
Collector<data> collector;
// Works perfectly fine
auto error = collector.average2<&data::velocity>();
}

在c++ 20中,您可以通过将field约束为Data成员指针来使其更简洁。这将为您提供更严格的重载解析以及更好的错误消息。

#include <type_traits>
template<typename PtrT, typename ObjT>
concept MemberObjectPointerFor = std::is_member_object_pointer_v<PtrT> &&
requires(PtrT ptr, ObjT& obj) {
{ obj.*ptr };
};
template <typename Data>
class Collector {
// ...
public:
template <MemberObjectPointerFor<Data> auto field>
auto average2() const {
using T = decltype(std::declval<Data>().*field);
return T{}; // Some calculation here
} 
};

相关内容

  • 没有找到相关文章

最新更新