为什么我的 SFINAE 检查不能使用 google 测试的 ASSERT_TRUE?

Why can't I use google test's ASSERT_TRUE for my SFINAE check?

我使用 C++17 的 std::void_t:

对静态成员函数的存在进行了简单的 SFINAE 检查
template <class T, class X = void>
struct has_bar {
    static const bool value = false;
};
template <class T>
struct has_bar<T, std::void_t<decltype(T::bar(std::declval<int&>()))>> {
    static const bool value = true;
};

class Foo 显然有一个 bar 成员函数以 int& 作为其唯一参数, class NoBar 有没有这样的成员函数:

struct Foo
{
    static void bar(int& value)
    {
        value = 42;
    }
};

struct NoBar{};

static_assert 中使用 has_bar 按预期工作,但在 ASSERT_TRUE 语句中使用它会产生编译器错误:

TEST(SFINAE, has_bar)
{
    static_assert(!has_bar<NoBar>::value);
    static_assert(has_bar<Foo>::value);
    ASSERT_FALSE(has_bar<NoBar>::value);

    //why does this not work??
    ASSERT_TRUE(has_bar<Foo>::value);
}

int main(int argc, char** argv)
{
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
ASM generation compiler returned: 0
/opt/compiler-explorer/gcc-10.2.0/bin/../lib/gcc/x86_64-linux-gnu/10.2.0/../../../../x86_64-linux-gnu/bin/ld: /tmp/ccfSP5vL.o: in function `SFINAE_has_bar_Test::TestBody()':
/home/ce/<source>:42: undefined reference to `has_bar<Foo, void>::value'
collect2: error: ld returned 1 exit status
Execution build compiler returned: 1

这是 google 测试错误还是我遗漏了什么?

出现此错误是因为 has_bar::value 已声明但未定义。 ASSERT_TRUE 宏以某种方式使用了该对象。没有必要确切地理解 ASSERT_TRUE 在做什么;你应该总是定义你的静态 class 成员。

最简单的方法是从 std::false_typestd::true_type 继承,而不是声明一个名为 value 的静态成员。标准库已包含继承 value 成员的定义,因此您不必提供自己的定义。

在 C++17 中,请注意 static constexpr bool value = false; 本身的定义(并且隐含地是 inline)。但如果成员只是 const 而不是 constexpr,则情况并非如此,因此您会在 C++14 和 C++17 模式下看到该问题。