如何使功能模板成为测试的参数?

时间:2018-11-10 11:04:36

标签: c++ templates

我想对类模板的等效模板化成员函数进行单元测试。 (作为背景,我想为库的“经典”功能符号的用户提供.bar()以及默认的符号|,&等,但我不想重复完整的测试代码。)

#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例如,报告我“重载函数'bar'的地址不能被static_cast键入'op_t'”

还是我走错了路,这是不可能的? (我尝试了clang 6和gcc 7)

1 个答案:

答案 0 :(得分:1)

我可以通过将op_t更改为

来编译代码
using op_t = foo<void>(foo<void>::*)(void_t &&) &&;
//                                          ^^

sut

auto sut = (foo<void>{}.*op)(*[](){});
//                           ^

({[](){}可以转换为函数指针,但是*op引用了一个函数,因此我们必须取消对该指针的引用)。

或者,您也可以将sut更改为

,而不是更改void_t
using void_t = void (*)();
//                  ^^^

现在void_t已经是一个函数指针,因此您不必取消引用。