首页 文章

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

提问于
浏览
29

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

询问的原因是以下代码,在链接时将错误地引用 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在整合东西方面,但我想知道:

Which compiler is correct and what does the standard say about it?


#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 回答

  • 17

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

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

  • 8

    n3242§14.7.1/ 1

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

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

    n3242§14.6.5/ 1

    可以在类模板中声明好友类或函数 . 实例化模板时,会将其朋友的名称视为在实例化时明确声明了特化 .

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

相关问题