为什么我的 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 测试错误还是我遗漏了什么?
- 实时代码 C++17:https://godbolt.org/z/fj8z6b
- 实时代码 C++14:https://godbolt.org/z/n7TvqW
出现此错误是因为 has_bar::value
已声明但未定义。 ASSERT_TRUE
宏以某种方式使用了该对象。没有必要确切地理解 ASSERT_TRUE
在做什么;你应该总是定义你的静态 class 成员。
最简单的方法是从 std::false_type
和 std::true_type
继承,而不是声明一个名为 value
的静态成员。标准库已包含继承 value
成员的定义,因此您不必提供自己的定义。
在 C++17 中,请注意 static constexpr bool value = false;
是 本身的定义(并且隐含地是 inline
)。但如果成员只是 const
而不是 constexpr
,则情况并非如此,因此您会在 C++14 和 C++17 模式下看到该问题。
我使用 C++17 的 std::void_t
:
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 测试错误还是我遗漏了什么?
- 实时代码 C++17:https://godbolt.org/z/fj8z6b
- 实时代码 C++14:https://godbolt.org/z/n7TvqW
出现此错误是因为 has_bar::value
已声明但未定义。 ASSERT_TRUE
宏以某种方式使用了该对象。没有必要确切地理解 ASSERT_TRUE
在做什么;你应该总是定义你的静态 class 成员。
最简单的方法是从 std::false_type
和 std::true_type
继承,而不是声明一个名为 value
的静态成员。标准库已包含继承 value
成员的定义,因此您不必提供自己的定义。
在 C++17 中,请注意 static constexpr bool value = false;
是 本身的定义(并且隐含地是 inline
)。但如果成员只是 const
而不是 constexpr
,则情况并非如此,因此您会在 C++14 和 C++17 模式下看到该问题。