【问题标题】:C++ class template specialization questionC++ 类模板专业化问题
【发布时间】:2011-07-18 14:10:07
【问题描述】:

通过查看以下代码,我对第 3 行感到困惑。
第 3 行不是基本模板的特例,它更像是“类重载”。但是可以编译成功。
第7行的obj1是按照第3行定义的,但是编译失败。
怎么会?

template<typename S,int T, void(* U)()> class Bar{};  // Base template
template<int T, void(* U)()> class Bar<double, T, U>{}; // Specialization, which is good
template<int T, void(* U)()> class Bar<double, U, T>{}; // Also good, how come?

void func(){};
int main(){
   //Bar<double, func, 1> obj1;   // Error, from line 3
}

【问题讨论】:

    标签: c++ templates specialization template-specialization


    【解决方案1】:

    模板很特别:你不使用的任何东西实际上都没有被实例化(编译)。这允许使用某些通用模板完成许多很酷的事情。例如,您可以定义根本不会使用某些类型参数进行编译的成员函数,但只要您不使用这些成员,就不会出错。

    这也可能会咬你一口:第 3 行实际上格式不正确——它是 Bar 的非编译特化——但在你真正尝试在 main() 函数中使用它之前,你不会注意到它。

    【讨论】:

    • 感谢您的回答。请在下面查看我跟随 Nim 的 cmets。
    【解决方案2】:

    只要该形式没有在任何地方使用 - 那么编译器就不会抱怨。如果使用它,并且编译器必须实例化 - 那么它会抱怨。这就是为什么如果您取消注释,您会收到错误 - 此时,编译器会看到有缺陷的部分特化。

    【讨论】:

    • 那么编译器什么时候应该抱怨,什么时候不应该抱怨呢?如果我在第 4 行添加另一行: template class Bar{};没有使用,编译器没有实例化,但是编译失败。
    • @John,就像我说的,如果您尝试声明该类型的实例(如取消注释 obj1 的行)(此时它会尝试实例化),它会抱怨。如果你不这样做就不会 - 这就是模板的美妙之处......
    • @John,这是一个不同的问题 - 你的模板参数比 Bar 需要的多。
    • 谢谢。我会记住它的规则。不过还是觉得这条规则没有意义:)
    • 如果您有一个永远无法使用的模板,编译器可以(但不是必须)抱怨。这可能是其中之一。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-18
    相关资源
    最近更新 更多