问题
Lets say I have a class holding some members of some type. I know that the syntax for try-catch blocks with initializer lists is as follows
template<int N>
struct Member
{
Member()
{
std::cout << "Default constructor of Member " << N << std::endl;
}
};
class A
{
Member<1> m1;
Member<2> m2;
// n members
public:
A() try
: m1()
, m2()
{
// constructor implementation
}
catch (std::exception const & e)
{
// ... cleanup
throw; // and rethrow
}
};
Since the initializer list is involved I can't use multiple try catch blocks. How can I tell which member initialization threw the exception?
回答1:
You can trace the initialization process
class A
{
Member<1> m1;
bool m1threw = true;
Member<2> m2;
bool m2threw = true;
// n members
public:
A() try
: m1()
, m1threw(false)
, m2()
, m2threw(false)
{
// constructor implementation
}
catch (std::exception const & e)
{
// ... cleanup
if (m1threw) {
//
}
else if (m2threw) {
}
throw; // and rethrow
}
};
Note In class initialization is only valid in c++11. What makes your example more complicated is that the member variables are default constructed. If their constructor accepted an argument, this would be a perfect match for the construction tracker idiom
I provided Member with a non default constructor to showcase an example of the construction tracer idiom
template<int N>
struct Member
{
Member(int some_arg)
{
std::cout << "Non default constructor of Meber " << N << std::endl;
}
};
class A
{
Member<1> m1;
Member<2> m2;
enum TrackerType { NONE, ONE, TWO };
public:
A(TrackerType tracker = NONE)
try // A constructor try block.
: m1((tracker = ONE, 1)) // Can throw std::exception
, m2((tracker = TWO, 1)) // Can throw std::exception
{
//TODO:
}
catch (std::exception const & e)
{
if (tracker == ONE) {
std::cout << "m1 threw: " << e.what() << std::endl;
}
else if (tracker == TWO) {
std::cout << "m2 threw: " << e.what() << std::endl;
}
throw;
}
};
Essentially this requires no extra members to achieve tracing as you can see and can compile with c++ prior to 11
回答2:
template<int N>
struct Member
{
Member()
{
std::cout << "Default constructor of Member " << N << std::endl;
// ...
if (bad_thing)
{
throw N;
}
}
};
class A
{
Member<1> m1;
Member<2> m2;
// n members
public:
A() try
: m1()
, m2()
{
// ...
}
catch (int N)
{
std::cout << "construction of member " << N << " failed" << std::endl;
// ...
}
};
来源:https://stackoverflow.com/questions/22260567/finding-which-member-in-an-initializer-list-threw-an-exception