我必须绕过void *以支持在编译时不知道的类型,但是我也不想完全发疯,把一切都留给自己,所以我认为对type_Checking使用type_info,但是type_info不支持复制操作,我在传递它们时遇到编译器错误
#include <bits/stdc++.h>
struct PropertyClassInterface {
virtual const char * name() = 0;
virtual void set(const char * property_name,std::pair<const void *,std::type_info> new_val) = 0;
virtual std::pair<std::shared_ptr<void>,std::type_info> get(const char * property_name) = 0;
template< typename Type>
static std::pair<std::shared_ptr<void>,std::type_info> get_type_pair(const Type& Value) {
std::shared_ptr<void> t = std::make_shared<Type>();
*static_cast<Type *>(t.get()) = Value;
*return std::make_pair(t,typeid(Type));* // error
}
};
struct PropertyManager {
using base_pointer = std::shared_ptr<PropertyClassInterface>;
void add_object(base_pointer new_member) {
objects.push_back(new_member);
}
template<typename Type>
void set(const char * object_name,const char * property_name,const Type& new_val) {
find_object_orThrow(object_name)->set(property_name,std::make_pair(static_cast<const void *>(&new_val),typeid(new_val)));
}
template<typename Type>
Type get(const char * object_name, const char * property_name) {
auto a = find_object_orThrow(object_name)->get(property_name);
if (typeid(Type).hash_code() != a.second.hash_code())
throw std::runtime_error{"get(): mismatched type"};
return a.first;
}
public:
std::vector<base_pointer> objects;
base_pointer find_object_orThrow(const char * obj_name){
for(auto& o : objects) {
if (!strcmpi(o->name(),obj_name)) {
return o;
}
}
throw std::runtime_error{std::string("no object named \"") + obj_name + "\" found"};
}
};
struct testClass : PropertyClassInterface {
void set(const char * property_name,std::pair<const void *,std::type_info> new_val) {
auto checkTypeInfo = [&new_val](const std::type_info& expected) {
if (new_val.second.hash_code() != expected.hash_code())
throw std::runtime_error{"set(): wrong type"};
};
if (!strcmpi(property_name,"my_number")) {
checkTypeInfo(typeid(decltype(my_number)));
my_number = *static_cast<const decltype(my_number) *>(new_val.first);
}
};
std::pair<std::shared_ptr<void>,std::type_info> get(const char * property_name) {
if (!strcmpi(property_name,"my_number")) {
PropertyClassInterface::get_type_pair(my_number);
}
}
private:
int my_number;
};
int main() {
};
所以我也必须使用动态内存来存储type_info
我仅限于c ++ 11,我知道不使用位头,而只是用于测试
答案 0 :(得分:0)
您要执行的是实施任何一项,或使用boost any。
任何东西都不难写。
namespace details {
struct any_concept;
using pimpl=std::unique_ptr<any_concept>;
struct any_concept {
virtual ~any_concept() {}
virtua pimpl clone() const = 0;
virtual std::type_info const& type() const = 0;
private:
virtual void* unsafe_get() = 0;
virtual void const* unsafe_get() const = 0;
public:
template<class T>
T* get() {
if (typeid(T) != type()) return nullptr;
return static_cast<T*>(unsafe_get());
}
template<class T>
T const* get() const {
if (typeid(T) != type()) return nullptr;
return static_cast<T const*>(unsafe_get());
}
};
template<class T>
struct any_model:any_concept {
T t;
virtual ~any_model() = default;
virtual pimpl clone() const final override {
return pimpl( new any_model(t) );
}
virtual std::type_info const& type() const final override {
return typeid(T);
}
template<class U>
any_model(U&& u):t(std::forward<U>(u)){}
private:
virtual void* unsafe_get() final override { return std::addressof(t); }
virtual void const* unsafe_get() const final override { return std::addressof(t); }
};
}
struct any {
template<class T, typename std::enable_if<!std::is_same<any, typename std::decay<T>::type>::value, bool> =true>
any( T&& t ):
pImpl( new details::any_model<typename std::decay<T>::type>( std::forward<T>(t) ) )
{}
template<class T>
T* get() {
if (!pImpl) return nullptr;
return pImpl->get<T>();
}
template<class T>
T const* get() const {
if (!pImpl) return nullptr;
return const_cast<details::any_concept const&>(*pImpl).get<T>();
}
template<class T>
bool contains()const { return get<T>(); }
explicit operator bool() const {
return (bool)pImpl;
}
any()=default;
any(any&&)=default;
any& operator=(any&&)=default;
~any()=default;
any(any const& o):
pImpl( o.pImpl?o.pImpl->clone():pimpl{} )
{}
any& operator=(any const& o) {
any tmp(o);
std::swap(*this, tmp);
return *this;
}
private:
details::pimpl pImpl;
};
有;一个非常简单的any
实现。写在电话上,因此可能包含错字。
它支持值语义,但存储任何内容(可以复制和销毁)。如果知道它存储的内容,则可以.get<T>()
。您也可以问它是否contains<T>()
。
这被称为词汇类型。基本上,这是您的void*
,并以一种使滥用更加困难的方式键入信息。