このコードはboost::anyに基づいています。型消去を使用して任意の値を格納し、その値への代入を禁止します。見やすいように、鋳造機を縞模様にしました。
完全な再実装を実行する代わりに、ラッピングである程度成功する可能性がありboost::any
ますが、それについてはわかりません。キャストには注意が必要です。
また、コピーと移動も禁止されています。これに対処するのは面倒ですが、完全な実装にはそれが必要です。
また、より意味のある名前を付けたいと考えています。
#include <typeinfo>
#include <iostream>
class reassign_any {
public:
reassign_any() : content_(nullptr) {}
template <typename T>
reassign_any(const T& x) : content_(new holder<T>(x)) {}
~reassign_any() {
// no need to check for null
delete content_;
}
reassign_any(const reassign_any&) = delete;
reassign_any& operator=(const reassign_any&) = delete;
reassign_any(reassign_any&&) = delete;
reassign_any& operator=(reassign_any&&) = delete;
bool empty() const { return !content_; }
template <typename T>
bool set(const T& t) {
if(content_) {
// check for type equality of held value and value about to be
// set
if(content_->type() == typeid(T)) {
delete content_;
content_ = new holder<T>(t);
return true;
} else {
return false;
}
} else {
// just create
content_ = new holder<T>(t);
return true;
}
}
template <typename T>
T* get() {
return content_->type() == typeid(T)
? &static_cast<holder<T>*>(content_)->held
: 0;
}
private:
class placeholder
{
public: // structors
virtual ~placeholder()
{
}
virtual const std::type_info & type() const = 0;
};
template<typename ValueType>
class holder : public placeholder
{
public: // structors
holder(const ValueType & value)
: held(value)
{
}
virtual const std::type_info & type() const
{
return typeid(ValueType);
}
public: // representation
ValueType held;
private: // intentionally left unimplemented
holder & operator=(const holder &);
};
private:
placeholder* content_;
};
int main()
{
reassign_any x;
x.set(3);
if(x.get<int>())
std::cout << "int set" << std::endl;
if(x.set(3.f)) {
std::cout << "this shouldn't be printed" << std::endl;
} else {
std::cout << "this should be printed" << std::endl;
}
if(x.set(23)) {
std::cout << "this should be printed" << std::endl;
} else {
std::cout << "this shouldn't be printed" << std::endl;
}
return 0;
}
無関係なメモ: Boost.TypeErasure は最近レビューを受けました。少なくとも実装がそれを可能にするかどうかを確認するために、このバージョンの any を実装してみたくなります。