Commit 13a9d276 authored by Paul's avatar Paul
Browse files

Add support for any_cast

parent 5f8d091d
......@@ -49,6 +49,29 @@ struct operation
return *this;
}
// Cast
template <typename PrivateDetailTypeErasedT>
PrivateDetailTypeErasedT* any_cast()
{
return private_detail_te_get_handle().type() == typeid(PrivateDetailTypeErasedT)
? std::addressof(static_cast<private_detail_te_handle_type<
typename std::remove_cv<PrivateDetailTypeErasedT>::type>&>(
private_detail_te_get_handle())
.private_detail_te_value)
: nullptr;
}
template <typename PrivateDetailTypeErasedT>
const typename std::remove_cv<PrivateDetailTypeErasedT>::type* any_cast() const
{
return private_detail_te_get_handle().type() == typeid(PrivateDetailTypeErasedT)
? std::addressof(static_cast<const private_detail_te_handle_type<
typename std::remove_cv<PrivateDetailTypeErasedT>::type>&>(
private_detail_te_get_handle())
.private_detail_te_value)
: nullptr;
}
std::string name() const
{
assert(private_detail_te_handle_mem_var);
......@@ -72,6 +95,7 @@ struct operation
{
virtual ~private_detail_te_handle_base_type() {}
virtual std::shared_ptr<private_detail_te_handle_base_type> clone() const = 0;
virtual const std::type_info& type() const = 0;
virtual std::string name() const = 0;
virtual shape compute_shape(std::vector<shape> input) const = 0;
......@@ -104,6 +128,11 @@ struct operation
return std::make_shared<private_detail_te_handle_type>(private_detail_te_value);
}
const std::type_info& type() const override
{
return typeid(private_detail_te_value);
}
std::string name() const override { return private_detail_te_value.name(); }
shape compute_shape(std::vector<shape> input) const override
......@@ -144,6 +173,38 @@ struct operation
std::shared_ptr<private_detail_te_handle_base_type> private_detail_te_handle_mem_var;
};
template <typename ValueType>
inline const ValueType* any_cast(const operation* x)
{
return x->any_cast<ValueType>();
}
template <typename ValueType>
inline ValueType* any_cast(operation* x)
{
return x->any_cast<ValueType>();
}
template <typename ValueType>
inline ValueType& any_cast(operation& x)
{
using type = typename std::remove_reference<ValueType>::type;
auto* y = x.any_cast<type>();
if(y == nullptr)
throw std::bad_cast();
return *y;
}
template <typename ValueType>
inline const ValueType& any_cast(const operation& x)
{
using type = typename std::remove_reference<ValueType>::type;
const auto* y = x.any_cast<type>();
if(y == nullptr)
throw std::bad_cast();
return *y;
}
} // namespace rtg
#endif
......@@ -6,6 +6,7 @@
struct simple_operation
{
int data = 1;
std::string name() const { return "simple"; }
rtg::shape compute_shape(std::vector<rtg::shape>) const { RTG_THROW("not computable"); }
rtg::argument compute(std::vector<rtg::argument>) const { RTG_THROW("not computable"); }
......@@ -20,4 +21,20 @@ void operation_copy_test()
EXPECT(op2.name() == op1.name());
}
int main() { operation_copy_test(); }
struct not_operation {};
void operation_any_cast()
{
rtg::operation op1 = simple_operation{};
EXPECT(rtg::any_cast<simple_operation>(op1).data == 1);
EXPECT(rtg::any_cast<not_operation*>(&op1) == nullptr);
EXPECT(test::throws([&]{ rtg::any_cast<not_operation&>(op1); }));
rtg::operation op2 = simple_operation{2};
EXPECT(rtg::any_cast<simple_operation>(op2).data == 2);
EXPECT(rtg::any_cast<not_operation*>(&op2) == nullptr);
}
int main() {
operation_copy_test();
operation_any_cast();
}
......@@ -27,6 +27,13 @@ namespace test {
TEST_FOREACH_OPERATOR(TEST_EACH_OPERATOR_OBJECT)
inline std::ostream& operator<<(std::ostream& s, std::nullptr_t)
{
s << "nullptr";
return s;
}
template <class T, class U, class Operator>
struct expression
{
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment