为什么我不能使用谷歌测试的ASSERT_TRUE进行SFINAE检查?



我使用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;
};

Foo显然有一个以int&为唯一参数的bar成员函数,类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

这是谷歌测试错误还是我在这里遗漏了什么?

  • 实时代码C++17:https://godbolt.org/z/fj8z6b
  • Live代码C++14:https://godbolt.org/z/n7TvqW

发生此错误是因为has_bar::value已声明但未定义。不知怎么的,ASSERT_TRUE宏已经odr使用了这个对象。不需要确切地了解ASSERT_TRUE在做什么;您应该始终定义静态类成员。

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

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

相关内容

  • 没有找到相关文章

最新更新