获取成员成员指针指向的类型



我想提取成员指针指向的成员类型。

template<someType myClass::*member>
void demo(myClass& instance, void* ptr) {
    instance.*member = *reinterpret_cast<someType*>(ptr);  // can the someType in this line be deduced from member?
}

我尝试按照评论中的建议使用decltype,但是我对此有问题:

instance.*member= static_cast<decltype(instance.*member)>((*buffer)[offset]);

bufferstd::shared_ptr<std::vector<uint8_t>>
someType uint32_t

我收到以下错误消息:

错误:类型中的static_cast无效 '__gnu_cxx::__alloc_traits>::value_type {aka unsigned char}' 键入 'uint32_t& {aka unsigned int&}'

据我了解,decltype(instance.*member) member定义为uint32_t instance::*member会产生参考uint32_t&而不是uint32_t。我尝试按值传递实例,但错误仍然存在。我知道std::remove_reference但是,我不明白参考首先是如何出现的。

进一步的改进是,如果我可以在没有类实例的情况下提取someType。但是我不知道如何实现这一点,而我可以通过拥有 std lib 来获取没有指针的类,例如:

template <T*>
struct removePointer {
  typedef T type;
}

我不知道如何以一种形式编写它,我可以在不先了解类的情况下获得类的someType部分。我可以写如下内容,但是我仍然必须显式传递类naem和typename,有没有办法自动提取它们?此外,以下 doe 首先不会编译 (http://ideone.com/8VlKO4): #include 使用命名空间标准;

template <class C,typename T, T C::*v>
struct getPointerType {
typedef T type;
};
class Test {
int value;
};
int main() {
int Test::*member=nullptr;
cout << typeid(getPointerType<Test, int, decltype(member)>::type) << std::endl;
return 0;
}

坦率地说,要理解您要实现的目标有点困难,因此我将专注于更新的部分。

显然,您不能将类型(派生自 decltype )作为值参数传递给模板。此外,您不能将非 constexpr 值作为模板参数传递(因此您不能只是将 member 变量粘贴到模板参数中并期望它编译)。

但是,您可以依靠编译器来推断出正确的函数来调用非costexpr变量:

template <class C, typename T>
T getPointerType(T C::*v);
class Test {
    int value;
};
int main() {
    int Test::*member=nullptr;
    cout << typeid(decltype(member)).name() << std::endl;
    cout << typeid(decltype(getPointerType(member))).name() << std::endl;
    return 0;
}

以上将打印:

M4Testi //int Test::*
i       //int

当然,有可能进一步"滥用"模板替换:

template <typename M>
struct getPointerType {
   template <typename C, typename T>
   static T get_type(T C::*v);
   typedef decltype(get_type(static_cast<M>(nullptr))) type;
};
class Test {
    int value;
};
int main() {
    int Test::*member=nullptr;
    cout << typeid(getPointerType<decltype(member)>::type).name() << std::endl;
    return 0;
}

输出将是预期的"i"。

以下是使用模板专用化技术的解决方案:

#include <type_traits>
template <class T>
struct member_type_helper;
template <class C, class T>
struct member_type_helper<T C::*> { using type = T; };
template <class T>
struct member_type
    : member_type_helper<typename std::remove_cvref<T>::type> {};
// Helper type
template <class T>
using member_type_t = member_type<T>::type;

使用示例 :

#include <iostream>
struct Foo { int i; };
int main()
{
    auto                ptr1 = &Foo::i;
    auto const&         ptr2 = &Foo::i;
    volatile auto const ptr3 = &Foo::i; // let's go crazy
    // prints true true true
    std::cout << std::boolalpha
              << std::same_as<int, member_type_t<decltype(ptr1)>> << 'n'
              << std::same_as<int, member_type_t<decltype(ptr2)>> << 'n'
              << std::same_as<int, member_type_t<decltype(ptr3)>> << 'n';
}

我想std::remove_cvref对于大多数用法来说可能是一种矫枉过正,但嘿,它是免费的。如果编译器不符合>C++20,则可以改用 std::remove_cv (> C++11)。

<小时 />

相关内容

  • 没有找到相关文章

最新更新