是否转换为指向模板的指针实例化该模板?

时间:2011-12-04 22:14:54

标签: c++ templates c++11 language-lawyer

static_cast<the_template<int>*>(0) - 这是否会以the_template类型实例化int

询问的原因是以下代码,在链接时将错误地引用check_error<char>(void*, long)与Clang和GCC 4.4.5的未定义引用,表明它没有实例化模板。然而,MSVC和GCC 4.5.1编译和链接很好,导致相信它 实例化模板。但是,如果省略演员阵容,MSVC和GCC(4.4.5和4.5.1)将仅在check_error<char>(想要的行为)上出错,而​​Clang在两次调用时都会出错。通常情况下,我相信Clang在整合方面,但我想知道:

哪种编译器正确,标准对此有何看法?


#include <type_traits>

template<class T>
void check_error(void*, long);

template<class T>
struct foo{
  template<class U>
  friend typename std::enable_if<
    std::is_same<T,U>::value
  >::type check_error(foo<T>*, int){}
};

template struct foo<int>;

int main()
{
  check_error<int>(static_cast<foo<int>*>(0), 0);
  check_error<char>(static_cast<foo<char>*>(0), 0);
}

2 个答案:

答案 0 :(得分:17)

实例化类模板特化,而不是函数调用,因为参数触发ADL。实例化完成是因为它的完整性可能会影响程序的语义。

那个铿锵不遵守这里的规范已经知道了,不久前我发了一封PR。见http://llvm.org/bugs/show_bug.cgi?id=9440

答案 1 :(得分:8)

n3242§14.7.1/ 1

  

除非已明确实例化(14.7.2)或明确专门化(14.7.3)类模板特化,   在上下文中引用特化时,隐式实例化类模板特化   当类类型的完整性影响语义时,它需要完全定义的对象类型或   程序。 类模板特化的隐式实例化导致隐式   类成员函数的声明的实例化,但不是定义或默认参数的实例化,   成员类,静态数据成员和成员模板;它会导致隐式实例化   成员匿名联盟的定义。除非是类模板的成员或成员模板   已经显式实例化或显式专门化,成员的特化是隐式实例化的   在需要成员定义存在的上下文中引用特化时;在   特别是,除非发生静态数据成员的初始化(以及任何相关的副作用)   静态数据成员本身的使用方式要求静态数据成员的定义存在。

在我看来,static_cast需要实例化声明,而不是定义(因为你只是处理指针)。

n3242§14.6.5/ 1

  

可以在类模板中声明好友类或函数。当模板被实例化时,   其朋友的名称被视为专业化已在实例化时明确声明。

我认为它应该链接,但也许其他人可以比我更好地解释。