Reputation: 705
I want to unit test equivalent templated member function of a class template. (As a background, I want to offer the users of the library "classical" function notation with .bar() and a tacit notation with |, &, etc. But I do not want to duplicate the complete test code.)
#include <utility>
template <typename T>
struct foo
{
template <typename U>
auto bar(U&& u)&& {
// whatever happens here.
return foo<T>();
}
template <typename U>
auto operator|(U&& u)&& {
return bar(std::forward<U>(u));
}
template <typename U>
auto bar(U&& u) const& {
// whatever happens here.
return foo<T>();
}
template <typename U>
auto operator|(U&& u) const& {
return bar(std::forward<U>(u));
}
};
int main() {
using void_t = void();
using op_t = foo<void>(foo<void>::*)(void_t)&&;
op_t ops[] = {static_cast<op_t>(&foo<void>::bar<void_t>),
static_cast<op_t>(&foo<void>::operator|<void_t>)};
for (const auto& op : ops) {
auto sut = (foo<void>{}.*op)([](){});
// test the behaviour of sut
}
}
clang e.g., reports me that "the address of overloaded function 'bar' cannot be static_cast to type 'op_t'"
Or am I on the wrong track and this is not possible? (I tried clang 6 and gcc 7)
Upvotes: 0
Views: 52
Reputation: 85767
I can get the code to compile by changing op_t
to
using op_t = foo<void>(foo<void>::*)(void_t &&) &&;
// ^^
and sut
to
auto sut = (foo<void>{}.*op)(*[](){});
// ^
([](){}
can be converted to a function pointer, but *op
takes a reference to a function, so we have to dereference the pointer).
Alternatively, instead of changing sut
, you can also change void_t
to
using void_t = void (*)();
// ^^^
Now void_t
is already a function pointer, so you don't have to dereference.
Upvotes: 1