Felix Petriconi
Felix Petriconi

Reputation: 705

How to make a function template a parameter to a test?

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

Answers (1)

melpomene
melpomene

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

Related Questions