Я хотел бы извлечь тип члена, на который указывает указатель члена.
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
Я получаю следующее сообщение об ошибке:
ошибка: недопустимый static_cast от типа
__ __gnu_cxx :: __ alloc_traits> :: value_type
{aka unsigned char} ‘для ввода ‘uint32_t& {иначе неподписанный 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):
#включают
использование пространства имен 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;
}
Результатом будет ожидаемое «я».
Других решений пока нет …