簡體   English   中英

獲取成員 memberpointer 指向的類型

[英]get type of member memberpointer points to

我想提取成員指針指向的成員的類型。

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>>
someTypeuint32_t

我收到以下錯誤消息:

錯誤:從類型'__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,有沒有辦法自動提取這些? 此外,以下內容首先沒有編譯( http://ideone.com/8VlKO4):#include using namespace std;

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)。


暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM