I'm trying to write a brief unit tester for a project I am working on.
This test passes if the given function throws a certain kind of exception:
template <class Exception, class Return, class... Args>
bool throws(std::string s, Return(*fn)(Args...), Args... args)
{
try
{
fn(args...);
}
catch (Exception& e)
{
return output(s, true);
}
catch (...)
{
return output(s, false);
}
return output(s, false);
}
Using it would look something like this:
throws<int>("Testing: Throws int", &foo);
And that works great. But now I'm trying to write a similar function that will work with member functions of a class.
Here's what I've got so far:
template <class Exception, class Object, class Return, class... Args>
bool throws(std::string s, Object& o, Return(Object::*fn)(Args...), Args... args)
{
// ...
(o.*fn)(args...);
// ...
}
template <class Exception, class Object, class Return, class... Args>
bool throws(std::string s, const Object& o, Return(Object::*fn)(Args...) const, Args... args)
{ /* ... */ }
Which should look something like this when used:
Bar<int> b1(5), b2(2);
typedef Bar<int>& (Bar<int>::*fn)(const Bar<int>&);
typedef Bar<int> (Bar<int>::*const_fn)(const Bar<int>&) const;
fn foo = &Bar<int>::foo;
const_fn const_foo = &Bar<int>::const_foo;
throws<int>("Testing member function", b1, foo, b2);
throws<int>("Testing const member function", b1, const_foo, b2);
But when I do this, I get "no matching function call" for both of these throws() functions. Specifically:
error: no matching function for call to ‘throws(const char [30], Bar<int>&, Bar<int> (Bar<int>::*&)(const Bar<int>&)const, const Bar<int>&)
And a similar one for the non-const version.
I noticed a few consts that were different, so I tried throwing in some const_cast's where I use the function, but no dice. This is the first time I've used member function pointers and variadic templates, (at all, let alone at the same time,) so I definitely could have missed something... anyone more experienced than me have any ideas?
The only thing I haven't been able to account for is the (Bar<int>::*&). The & at the end of that doesn't match the call... but that shouldn't be a problem, should it?
EDIT : As requested, my Bar class:
template <class T>
class Bar
{
private:
T _data;
public:
Bar (const int i) : _data(i) {}
Bar const_foo (const Bar& other) const
{
if (_data != other._data)
{
throw _data;
}
return Bar(_data);
}
Bar& foo (const Bar& other)
{
if (_data != other._data)
{
throw _data;
}
return *this;
}
};
And the full errors:
test.cpp: In function ‘int main()’:
test.cpp:111:53: error: no matching function for call to ‘throws(const char [24], Bar<int>&, Bar<int>& (Bar<int>::*&)(const Bar<int>&), Bar<int>&)’
test.cpp:111:53: note: candidates are:
test.cpp:31:6: note: template<class Exception, class Return, class ... Args> bool throws(std::string, Return (*)(Args ...), Args ...)
test.cpp:53:6: note: template<class Exception, class Object, class Return, class ... Args> bool throws(std::string, Object&, Return (Object::*)(Args ...), Args ...)
test.cpp:75:6: note: template<class Exception, class Object, class Return, class ... Args> bool throws(std::string, const Object&, Return (Object::*)(Args ...)const, Args ...)
test.cpp:112:65: error: no matching function for call to ‘throws(const char [30], Bar<int>&, Bar<int> (Bar<int>::*&)(const Bar<int>&)const, Bar<int>&)’
test.cpp:112:65: note: candidates are:
test.cpp:31:6: note: template<class Exception, class Return, class ... Args> bool throws(std::string, Return (*)(Args ...), Args ...)
test.cpp:53:6: note: template<class Exception, class Object, class Return, class ... Args> bool throws(std::string, Object&, Return (Object::*)(Args ...), Args ...)
test.cpp:75:6: note: template<class Exception, class Object, class Return, class ... Args> bool throws(std::string, const Object&, Return (Object::*)(Args ...)const, Args ...)
throws()functions" ...