Mit*_*vec 4 c++ templates googletest
我正在尝试将Google Test(gtest)代码移植到VxWorks 5.5.严重的缺点是开发环境Tornado 2.2使用古老的GCC编译器版本2.96.
在分析代码时,我找到了部分代码,gtest.h我不明白!这个C++模板类是如何运作的?
// ImplicitlyConvertible<From, To>::value is a compile-time bool
// constant that's true iff type From can be implicitly converted to
// type To.
template <typename From, typename To>
class ImplicitlyConvertible {
private:
// We need the following helper functions only for their types.
// They have no implementations.
// MakeFrom() is an expression whose type is From. We cannot simply
// use From(), as the type From may not have a public default
// constructor.
static From MakeFrom();
// These two functions are overloaded. Given an expression
// Helper(x), the compiler will pick the first version if x can be
// implicitly converted to type To; otherwise it will pick the
// second version.
//
// The first version returns a value of size 1, and the second
// version returns a value of size 2. Therefore, by checking the
// size of Helper(x), which can be done at compile time, we can tell
// which version of Helper() is used, and hence whether x can be
// implicitly converted to type To.
static char Helper(To);
static char (&Helper(...))[2]; // NOLINT
// We have to put the 'public' section after the 'private' section,
// or MSVC refuses to compile the code.
public:
// MSVC warns about implicitly converting from double to int for
// possible loss of data, so we need to temporarily disable the
// warning.
#ifdef _MSC_VER
# pragma warning(push) // Saves the current warning state.
# pragma warning(disable:4244) // Temporarily disables warning 4244.
static const bool value =
sizeof(Helper(ImplicitlyConvertible::MakeFrom())) == 1;
# pragma warning(pop) // Restores the warning state.
#elif defined(__BORLANDC__)
// C++Builder cannot use member overload resolution during template
// instantiation. The simplest workaround is to use its C++0x type traits
// functions (C++Builder 2009 and above only).
static const bool value = __is_convertible(From, To);
#else
static const bool value =
sizeof(Helper(ImplicitlyConvertible::MakeFrom())) == 1;
#endif // _MSV_VER
};
Run Code Online (Sandbox Code Playgroud)
创建此类的对象时,value如果模板类型From可隐式转换为模板类型,则具有名称的布尔变量应包含答案To.为了得到答案,使用了两个私有函数,MakeFrom()和Helper().但这两个函数只在这里声明,我找不到它们的定义.如果没有别的,这个实现不应该链接.
我也不理解以下语法
static char (&Helper(...))[2];
Run Code Online (Sandbox Code Playgroud)
当然,这段代码编译得很好(在Microsoft Visual C++ 7.1或更高版本或GCC 3.4或更新版本下),谷歌的人确切知道他们在做什么.
请赐教!不了解这段代码会让我发疯!:)
Jon*_*Jon 11
这是模板编程的标准技巧.
请注意,注释说"通过检查Helper(x)的大小":这强调了代码所做的唯一事情Helper是评估sizeof(Helper(x))一些x.该sizeof运营商实际上并没有评估它的参数(它并不需要;它只需要找出它有多大,这是有可能仅用资料在编译时),这就是为什么没有链接错误(Helper从不真的叫.)
给你带来麻烦的语法意味着这Helper是一个接受任何数量和类型的参数并返回对a的引用的函数char[2].要为这种类型的函数(可变函数)编写签名,需要使用省略号(...)作为最后一个参数的规范.
变量函数是从C继承的特性,通常应该避免使用,并且在与类类型一起使用时会造成严重破坏,但在这种情况下它并不重要,因为 - 如前所述 - Helper实际上不会被调用.
该类通过允许您使用语法将所有这些联系在一起
ImplicitlyConvertible<From, To>::value
Run Code Online (Sandbox Code Playgroud)
为了生成value,代码"伪造"调用Helper并传递一个From作为参数的实例¹.它依赖于编译器的重载决策来确定To在这种情况下是否会调用带有a的重载; 如果是这样,那个重载的返回值是char有保证大小的1,value最终是true.否则,选择可变重载(可以采用任何类型的参数),返回a char[2].这个尺寸大于1,所以value最终false.
¹请注意,这里" sizeof不实际评估表达式"技巧再次使用:如何告诉编译器参数Helper是一个实例From?你可以使用From(),但是From需要有一个默认的公共构造函数来编译代码.所以你只需告诉编译器"我有一个函数MakeFrom返回一个From" - 该函数实际上不会被调用.