[英]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]);
buffer
是std::shared_ptr<std::vector<uint8_t>>
,
someType
是uint32_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.