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

发布于 2024-12-19 06:55:21 字数 1036 浏览 3 评论 0 原文

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

询问的原因是以下代码,该代码在使用 Clang 和 GCC 4.4.5 链接时会出错,并带有对 check_error(void*, long) 的未定义引用,表明它实例化模板。然而,MSVC 和 GCC 4.5.1 编译和链接得很好,导致人们相信它确实实例化了模板。但是,如果省略强制转换,MSVC 和 GCC(4.4.5 和 4.5.1)将仅在 check_error 上出错(所需的行为),而 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);
}

static_cast<the_template<int>*>(0) - does this instantiate the_template with type int?

The reason for asking is the following code, which will error at linking time with an undefined reference to check_error<char>(void*, long) with Clang and GCC 4.4.5, indicating that it does not instantiate the template. MSVC and GCC 4.5.1 however compile and link just fine, leading to the believe that it does instantiate the template. However, if you leave out the cast, MSVC and GCC (both 4.4.5 and 4.5.1) will error on check_error<char> only (the wanted behaviour), while Clang will error on both calls. Normally I believe Clang when it comes to conforming stuff, but I wonder:

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);
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

黯淡〆 2024-12-26 06:55:21

实例化类模板特化的不是强制转换,而是函数调用,因为参数会触发 ADL 。之所以进行实例化,是因为它的完整性可能会影响程序的语义。

已知 clang 不遵循此处的规范,并且我前段时间发送了 PR。请参阅http://llvm.org/bugs/show_bug.cgi?id=9440

It is not the cast that instantiates the class template specialization, but the function call, because the argument triggers ADL . The instantiation is done because the completeness of it may affect the semantics of the program.

That clang does not follow the spec here is known and a PR was sent by me some time ago. See http://llvm.org/bugs/show_bug.cgi?id=9440

宁愿没拥抱 2024-12-26 06:55:21

n3242 §14.7.1/1

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

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

n3242 §14.6.5/1

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

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

n3242 §14.7.1/1

Unless a class template specialization has been explicitly instantiated (14.7.2) or explicitly specialized (14.7.3),
the class template specialization is implicitly instantiated when the specialization is referenced in a context
that requires a completely-defined object type or when the completeness of the class type affects the semantics
of the program.
The implicit instantiation of a class template specialization causes the implicit
instantiation of the declarations, but not of the definitions or default arguments, of the class member functions,
member classes, static data members and member templates; and it causes the implicit instantiation
of the definitions of member anonymous unions. Unless a member of a class template or a member template
has been explicitly instantiated or explicitly specialized, the specialization of the member is implicitly instantiated
when the specialization is referenced in a context that requires the member definition to exist; in
particular, the initialization (and any associated side-effects) of a static data member does not occur unless
the static data member is itself used in a way that requires the definition of the static data member to exist.

It seems to me that static_cast would require the instantiation of the declarations, but not of the definitions (as you are just dealing with pointers).

n3242 §14.6.5/1

Friend classes or functions can be declared within a class template. When a template is instantiated, the
names of its friends are treated as if the specialization had been explicitly declared at its point of instantiation.

I think that it should link, but maybe someone else can interpret better than I can.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文