【问题标题】:Does casting to a pointer to a template instantiate that template?转换为指向模板的指针是否会实例化该模板?
【发布时间】:2012-01-12 19:41:58
【问题描述】:

static_cast<the_template<int>*>(0) - 这是否将 the_template 实例化为 int 类型?

询问的原因是下面的代码,它会在使用 Clang 和 GCC 4.4.5 与 check_error<char>(void*, long) 的未定义引用链接时出错,表明它没有实例化模板。 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);
}

【问题讨论】:

  • @Matteo:自己写enable_ifis_same 并不难,这是我在 Comeau 测试时所做的,但后来我注意到与 R.Martinho 所做的相同 - Comeau Online 确实如此不链接。 :(
  • 这看起来像个糟糕的设计。只是远离语言的黑暗角落。你的问题少,别人的问题也少。 :-)
  • 我敢打赌,从一个指针到另一个指针的static_cast 要求底层类型是完整的。如果类型不相关,则强制转换必须失败,如果是,则强制转换必须执行必要的多态转换。
  • @Alf:但是我喜欢编译/链接时错误而不是运行时错误,这对于我正在编写的应用程序实际上是有意义的(我知道,他们都这么说)。 :(
  • @KerrekSB 我没有看到任何地方明确说明,但我认为类型必须完整才能确定是否应该可以确定static_cast 的结果。我不清楚是否真的必须实例化模板。

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


【解决方案1】:

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

众所周知,clang 不遵循这里的规范,并且我前段时间发送了一个 PR。见http://llvm.org/bugs/show_bug.cgi?id=9440

【讨论】:

  • 当。有什么方法可以在这里实现我想要的吗?如果某个模板尚未实例化,则编译器/链接器错误?
  • 另外,任何标准报价?还是@Dave 已经有了正确的?
  • @Xeo 相关的文字是他所做的没有加粗:) 是“或者当类类型的完整性影响程序的语义时”。请注意,这在 14.7.1p5 重复,但插入了 might 一词 - “可能会影响程序的语义”。这样做是因为在实例化之前,编译器无法知道语义是否会受到实例化的影响——它只有在事后才知道:)
  • @JohannesSchaub-litb 我更改了粗体部分
【解决方案2】:

n3242 §14.7.1/1

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

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

n3242 §14.6.5/1

Friend 类或函数可以在类模板中声明。当一个模板被实例化时, 其朋友的名称被视为在其实例化时已明确声明了特化。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多