模板与非模板类,跨编译器的不同行为

2024-05-11

我在一些应用程序中使用编译时计数器,它确实很有用。昨天我想用 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:一些输出:

  • VC2010:

    Templated
    a = 0
    b = 1
    
  • 海湾合作委员会4.8.1 http://codepad.org/llIzDOq3:

    Templated
    a = 1
    b = 1
    
  • 铿锵3.4 http://coliru.stacked-crooked.com/a/38ef15ceba198e80(感谢 dyp):

    Templated
    a = 0
    b = 1
    

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(使用前将#替换为@)

模板与非模板类,跨编译器的不同行为 的相关文章