我在一些应用程序中使用编译时计数器,它确实很有用。昨天我想用 gcc 编译一个程序(我之前使用的是 msvc),并且计数器的行为在模板类中发生了变化(它在模板类中不再工作)。
过于简化的代码:
// Maximum value the counter can hold
#define MAX_COUNT 64
// Used to store a number as the size of the structure
template<unsigned int n> struct Count { bool data[n]; };
// Used to overload functions while automatically selecting the
// right one based on the counter value (see following code)
template<int n> struct cn : public cn<n-1> {};
template<> struct cn<0> {};
struct Test
{
#define COUNT \
((sizeof(f(cn<MAX_COUNT + 1>())) / sizeof(bool)) - 1)
static Count<1> f(cn<1>);
/*
f(cn<65>()) will 'call' f(cn<1>) and return a Count<1> with size 1
-> count = 0;
*/
static const int a = COUNT;
static Count<COUNT + 2> f(cn<COUNT + 2>); // increase counter
/*
now Count<2> f(cn<2>) is defined, so:
f(cn<65>()) will 'call' f(cn<2>) and return a Count<2> with size 2
-> count = 1;
*/
static const int b = COUNT;
};
这个想法是使用函数重载,如果你测试上面的代码会完美工作 http://codepad.org/ypU9L0dS (a == 0
and b == 1
).
但是,如果结构体Test
制作模板(只需添加template<something>
例如在声明之前,不需要使用模板参数),计数器坏了 http://codepad.org/VxexSOjS我最终得到a == b == 1
。它还意味着在这些条件下不可能增加计数器。
这是我的问题:
- 这里有哪些模板规则在起作用?
- 为什么会有这种特定行为?
- 您有办法让计数器真正发挥作用吗?
注意:我想要一个与旧编译器兼容的 C++03 答案(即使我很想知道该特定情况的规则是否针对 C++11 发生了变化)
EDIT:一些输出:
EDIT 2
海湾合作委员会似乎采取Count
作为从属名称,如在这里可以观察到 http://coliru.stacked-crooked.com/a/daa2c7d956f9ea9a(感谢 dyp)。我在 gcc bugzilla 中发布了错误报告here http://gcc.gnu.org/bugzilla/show_bug.cgi?id=61103.
这可能是 C++ 中两阶段名称查找的属性。这是 C++03 的一个特性,C++11 中也存在。 LLVM 项目做了一个article http://blog.llvm.org/2009/12/dreaded-two-phase-name-lookup.html关于此功能并将其 Clang 编译器与 GCC 和 Visual C++ 进行比较。 GCC 和 Visual C++ 不支持此功能,但 Visual C++ 确实有一种处理名称查找的方法,该方法将允许依赖于两阶段查找的代码比在 GCC 上更频繁地工作。根据本文所述,它还允许非有效 C++ 代码的代码也能正常工作。
EDIT:我误读了这篇文章,GCC确实实现了两阶段查找,但它可以选择延迟查找直到模板实例化。但这似乎确实是 GCC 中的一个错误。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)