可能我不是第一个发现std::exception_ptr可以用来实现any类型的人(性能考虑被放在一边),因为它可能是C++中唯一可以容纳任何东西的类型.然而,谷歌搜索没有带来任何这方面的结果.
有没有人知道以下方法是否曾用于任何有用的方法?
#include <exception>
#include <iostream>
struct WrongTypeError : std::exception { };
class Any {
public:
template <class T>
void set (T t) {
try { throw t; }
catch (...) { m_contained = std::current_exception(); }
}
template <class T>
T const & get () {
try { std::rethrow_exception (m_contained); }
catch (T const & t) { return t; }
catch (...) { throw WrongTypeError {}; }
}
private:
std::exception_ptr m_contained = nullptr;
};
int main () {
auto a = Any {};
a.set (7);
std::cout << a.get<int> () << std::endl;
a.set (std::string {"Wonderful weather today"});
std::cout << a.get<std::string> () << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
因为它可能是C++中唯一可以容纳任何东西的类型.
我担心情况并非如此.boost :: any可以保存任何类型,甚至副本(假设类型是可复制的)也是正确的.它(广泛地说)使用基类和模板化子项实现:
class any_base {
...
}
template <class T>
class any_holder : public any_base
{
private:
T m_data;
}
Run Code Online (Sandbox Code Playgroud)
从中你可以想象你可以将任何类型填充到any_holder(使用正确的接口),然后你可以通过指向any_base的指针来保存any_holder.这种技术是一种类型的擦除; 一旦我们有一个any_base指针,我们持有一个对象,但对该类型一无所知.你可以说这是全类型擦除,类似std :: function提供部分类型擦除(并且可能在引擎盖下使用类似的技术,我不确定是否在我的头顶).
boost :: any提供了额外的接口来支持其使用任何类型,并且它可能提供更好的性能,因为抛出异常是疯狂的慢.另外,正如我之前提到的,它正确地复制了底层对象,这非常酷.exception_ptr是一个共享的所有权指针,所以我相信它会生成浅拷贝.
提升任何网站:http://www.boost.org/doc/libs/1_59_0/doc/html/any.html
它正在考虑我认为的标准:http://en.cppreference.com/w/cpp/experimental/any
看起来实现类似于boost,但增加了一个小对象优化.
就我所知,exception_ptr是一个非常奇怪的野兽,我之前遇到过它并用谷歌搜索它,那里的信息很少.我很确定它是神奇的,即它无法在用户空间中实现.我这样说是因为当你抛出它时,这种类型似乎神奇地消失了,这通常是不可能的.