【发布时间】:2014-05-07 18:37:38
【问题描述】:
我在一些应用程序中使用了编译时计数器,它真的很有用。昨天我想用 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;
};
这个想法是使用函数重载,如果你测试上面的代码will work perfectly(a == 0和b == 1)。
但是,如果将结构 Test 设为模板(例如,只需在其声明之前添加 template<something>,则无需使用模板参数),the counter breaks 和我最终得到 a == b == 1。这也意味着在这些情况下不可能增加计数器。
所以这是我的问题:
- 这里有哪些模板规则?
- 为什么会有这种特定行为?
- 您是否有让计数器实际工作的变通办法?
注意:我想要一个与旧编译器兼容的 C++03 答案(即使我很想知道针对 C++11 的特定情况的规则是否改变了)
编辑:一些输出:
-
VC2010:
Templated a = 0 b = 1 -
Templated a = 1 b = 1 -
Clang 3.4(感谢 dyp):
Templated a = 0 b = 1
编辑 2
GCC 似乎将 Count 作为依赖名称,作为 observable here(感谢 dyp)。我在 gcc bugzilla here 中发布了一个错误报告。
【问题讨论】:
-
看了一下宏
__COUNTER__? -
__COUNTER__在这里不是一个选择,因为 1/ 每个翻译单元都是全局的,2/ 每次使用都会增加,3/ 这个宏只能有 1 个计数器... -
#define MAX_COUNT 64:( 即使在 C++03 中也有很多不错的选择。为什么在这里使用宏? -
clang++3.4 和 g++4.8.2 之间的不同行为——clang++ 输出
0 1,g++ 输出1 1。所以要么是编译器错误,要么是未指定/未定义的行为。 -
@Danvil haha... 在我拥有的一些模板元编程旁边,这可以称为“简单”。 致所有人:I posted a bug report in gcc bugzilla,让我们看看他们是否找到了一些东西(至少回答;))