Skip to content

Instantly share code, notes, and snippets.

@EricWF
Last active August 29, 2015 14:14
Show Gist options
  • Select an option

  • Save EricWF/fe5543746711479c9b80 to your computer and use it in GitHub Desktop.

Select an option

Save EricWF/fe5543746711479c9b80 to your computer and use it in GitHub Desktop.
fundamentals TS and `std::any_cast<T &>((any*)nullptr))`

I wanted to talk to you about how I handle std::any_cast<int &>(static_cast<any *>(nullptr)). The current fundamentals draft is not clear about how what happens when you call the non-throwing any_cast with a reference type. However there is a problem.

The signature of the non_throwing any_cast is as follows:

template<class ValueType>
const ValueType* any_cast(const any* operand) noexcept;

template<class ValueType>
ValueType* any_cast(any* operand) noexcept;

So when you instantiate any_cast<T&>(any*) you attempt to create the return type by adding a pointer to a reference. This causes the non-throwing any_cast to drop out of the overload resolution set. Now the overload resolution set only contains the throwing versions of any_cast. Since any has a non-explicit converting constructor C++ decides to construct a new any from the any pointer and then call the non-throwing any_cast. Then at run time when you make the call to any_cast it will throw an exception.

I think that the non-throwing any_cast should fail to compile when you ask it to cast a reference type. I think the best way to achieve this is to change the signatures of the non-throwing any_cast to the following and add internal static asserts that ValueType is not a reference.

template<class ValueType>
add_pointer_t<add_const_t<ValueType>> any_cast(const any* operand) noexcept;

template<class ValueType>
add_pointer_t<ValueType> any_cast(any* operand) noexcept;

We should also fix the draft as well. Let me know if you have any questions.

#include <experimental/any>
using std::experimental::any;
using std::experimental::any_cast;
int main()
{
any a(1);
any_cast<int &>(&a); // shouldn't compile!
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment