什么时候应该对非限定函数调用进行名称查找 - 使用依赖空指针常量表达式参数调用?

时间:2013-08-04 22:17:01

标签: c++ templates null expression language-lawyer

Clang 3.0拒绝以下代码,抱怨未找到g(unsigned long)。 GCC 4.8接受它没有错误。

void g(int*);

void f()
{
    g(sizeof(int) - sizeof(int)); // ok, evaluates to 0
}

template<typename T>
struct A
{
    void f()
    {
        g(sizeof(T) - sizeof(T)); // error: no matching function
    }
};

我对该标准的解读表明,'g'不是一个依赖名称,应该像clang似乎一样立即查找并绑定。即便如此,标准指定的行为似乎也是错误的,因为g否则会在实例化时正确绑定。

  

[temp.dep]
  [...]表达形式:
  postfix-expression ( expression-list <子>选择 )
  其中postfix-expression是一个id-expression,如果expression-list中的任何表达式是依赖于类型的表达式(14.6.2.2),或者id-的非限定id,则id-expression表示一个从属名称。 expression是一个template-id,其中任何模板参数都依赖于模板参数。   如果运算符的操作数是类型相关的表达式,则运算符也表示从属名称。   这些名称是未绑定的,在模板定义的上下文和实例化的上下文中都会查看模板实例化(14.6.4.1)。

此方案中的合规行为是什么?

1 个答案:

答案 0 :(得分:1)

事实证明,由于C ++标准中的已知缺陷,此行为未指定:

http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html

  

DR 903.依赖于值的整数空指针常量

建议的解决方案是改变标准的措辞,只允许文字“0”作为空指针常量,但这正在审查中,因为它意味着破坏使用“假”的现有代码。

GCC似乎通过将'g'视为依赖名称来解决此问题。相比之下,Clang似乎认为依赖于值的表达式永远不能是空指针常量表达式。这两种方法都不是严格正确的,因为没有指定正确的行为。