这是我一直在尝试调查的用例的简单版本
#include<iostream>
#include<stdexcept>
#include<memory>
#include<type_traits>
#include<string>
class intexception:public std::exception
{
public:
intexception(std::string m,int x):msg(m),g(x){}
const char* what() const throw() { return msg.c_str(); }
virtual ~intexception() throw(){}
int getExceptInt()const { return g;}
private:
std::string msg;
int g;
};
class Int
{
public:
Int():m_ptr(nullptr){}
Int(const int& x) : m_ptr(new int(x)) { }
Int(const Int& in) : m_ptr( (in.get()) ? ( new int(*in.m_ptr) ) : ( nullptr ) ) {}
Int& operator=(const Int&) = default;
Int(Int&&) = default;
Int& operator=(Int&&) = default;
int get() const { return *m_ptr; }
private:
std::unique_ptr<int>m_ptr;
};
class TypedInt
{
public:
template<typename T,
typename std::enable_if< std::is_same<typename std::decay<T>::type,int>::value || std::is_same<typename std::decay<T>::type,long>::value,
std::nullptr_t>::type = nullptr>
explicit TypedInt (T& intid )
: m_holder( intid ),
m_throw ( [this]() { throw intexception("Integer Exception",static_cast<T>(this->get())); } )
{}
TypedInt():m_holder(),m_throw(std::function<void()>()){}
TypedInt& operator=(TypedInt&&) = default;
TypedInt(TypedInt&& other):m_holder(std::move(other.m_holder)),m_throw(std::move(other.m_throw)) {}
TypedInt& operator=(const TypedInt&) = default;
TypedInt(const TypedInt&) = default;
int get() const { return m_holder.get(); }
void Throw() { m_throw(); }
private:
Int m_holder;
std::function<void()>m_throw;
};
void testThrow(TypedInt t)
{
try
{
t.Throw();
}
catch(const intexception& e)
{
std::cout<<e.what()<<std::endl;
std::cout<<e.getExceptInt()<<std::endl;
}
}
int main()
{
int z = 10;
TypedInt t1(z);
TypedInt t2;
t2 = std::move(t1);
testThrow(std::move(t2));
return 0;
}
这可以正常编译,没有问题。但是,它最终会出现段错误。
我看了这个link我觉得我可能面临类似的问题。
我已经用 gdb 对此进行了调试,但我无法理解为什么此 get()
函数会为我的 std 中的基础整数返回一个
成员变量。null
值: :unique_ptr
最佳答案
当你构造t1
时,你构造它的m_throw
有:
m_throw ([this]() {
throw intexception("Integer Exception",static_cast<T>(this->get()));
})
也就是说,t1.m_throw
持有t1
(通过指针)。它抛出一个从 t1.m_holder.get()
构造的 intexception
。
当您将其移动到 t2
时 - std::function
中的实际底层 lambda 不会改变。它仍在尝试抛出 t1.m_holder.get()
。问题是,一旦您从 t1.m_holder
移动,取消引用底层 unique_ptr
是无效的 - 这是您的段错误的根源。
您必须重新绑定(bind) throw 器以确保您始终从this
throw 。最简单的方法就是将 TypedInt
实例作为参数传入,这样您就不必担心任何事情。
关于c++ - 使用 lambdas 将模板类型的成员作为异常抛出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37117267/