gpt4 book ai didi

c++ - 这个 C++ 模板类代码是如何工作的?

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:11:03 26 4
gpt4 key购买 nike

我正在尝试将 Google 测试 (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
};

创建此类的对象时,如果模板类型 From 可隐式转换为模板类型 To<,则名称为 value 的 bool 变量应包含答案。为了得到答案,使用了两个私有(private)函数,MakeFrom()Helper()。但这两个函数只在这里声明,我找不到它们的定义。如果不出意外,此实现不应链接。

我也不明白下面的语法

static char (&Helper(...))[2];

当然,这段代码编译得很好(在 Microsoft Visual C++ 7.1 或更高版本或 GCC 3.4 或更高版本下),Google 的人很清楚他们在做什么。

请赐教!不理解这段代码会让我发疯! :)

最佳答案

这是模板编程的标准技巧。

请注意,注释说“通过检查 Helper(x) 的大小”:这强调了代码唯一Helper 做的事情正在评估sizeof(Helper(x))对于一些 x . sizeof operator 实际上并不评估它的参数(它不需要;它只需要找出它有多大,这可以只使用编译时可用的信息),这就是为什么有没有链接器错误(从未真正调用过 Helper)。

给你带来麻烦的语法意味着Helper是一个接受任意数量和类型的参数并返回对 char[2] 的引用的函数.要为这种类型的函数(variadic function)编写签名,需要使用省略号(...)作为最后一个参数的规范。

可变参数函数是从 C 继承的一个特性,通常应该避免,并且在与类类型一起使用时会造成严重破坏,但在这种情况下无关紧要,因为 -- 如前所述 -- Helper不会被实际调用。

该类通过允许您使用语法将所有这些联系在一起

ImplicitlyConvertible<From, To>::value

生产value ,代码“伪造”调用Helper并传递给它一个 From 的实例作为论点¹。它依赖于编译器的重载解析来确定重载是否采用 To。在这种情况下会被调用;如果是这样,该重载的返回值为 char保证大小为 1value最终成为 true .否则选择可变参数重载(可以采用任何类型的参数),返回 char[2] .它的大小大于 1 , 所以 value结束 false .


¹ 请注意,这里再次使用了“sizeof 实际上不计算表达式”的技巧:如何告诉编译器 Helper 的参数是 From 的实例?你可以使用 From() ,然后 From需要有一个默认的公共(public)构造函数来编译代码。因此,您只需告诉编译器“我有一个返回 MakeFrom 的函数 From”——实际上不会调用该函数。

关于c++ - 这个 C++ 模板类代码是如何工作的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12244744/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com