【问题标题】:Template method specialization for const char*const char* 的模板方法特化
【发布时间】:2017-07-30 10:17:11
【问题描述】:

考虑一下这个sn-p:

struct S {
    template <typename T>
    void insert(const T& x);
};

template <>
void S::insert<char*>(const char*& x) {}

int main() {
  S s;
  s.insert("");
  return 0;
}

gcc 编译失败,错误信息如下:

error: template-id 'insert<char*>' for 'void S::insert(const char*&)' does not match any template declaration

这个错误的原因是什么,有没有办法编写专业化以便它可以工作?

我不是在寻找替代解决方案,我只是想了解错误背后的逻辑。

【问题讨论】:

    标签: c++ templates template-specialization specialization


    【解决方案1】:

    你指定了错误的参数类型。

    请注意,对于 const T&amp;const 是在 T 本身上限定的。那么对于T = char*const T&amp; 应该是char* const &amp;(即引用const 指针),而不是const char* &amp;(即引用指向const 的指针)。

    BTW Clang 给出更清晰的错误信息:

    候选模板被忽略:无法将 'void (char *const &)' 与 'void (const char *&)' 匹配


    再次顺便说一句,对于s.insert("");,不会调用规范,因为"" 确实是const char[1],那么T 的类型将被推断为char [1],这与@987654337 不匹配@。如果您希望规范适用于char[1],那么它应该是

    template <>
    void S::insert<char[1]>(char const (&) [1]) {}
    

    然后

    S s;
    s.insert("");
    

    但它只适用于char[1],即只有一个元素的char 数组。我认为让它与const char* 一起工作会更有意义,那么它应该是

    template <>
    void S::insert<const char*>(const char * const &) {}
    

    然后

    S s;
    const char* str = "";
    s.insert(str);
    

    【讨论】:

    • 我实际上已经尝试过了,但 gcc 仍然无法编译/链接它:undefined reference to 'void S::insert&lt;char [1]&gt;(char const (&amp;) [1])'
    • @FrançoisBeaune 答案已修改。
    • 是否有可能声明一个衰减的专业化转发到const char* 一个,例如开始处理s.insert("")(字面意思)的案例?
    • @dfri 不,主模板被声明为引用,那么T 将始终被推导出为数组;如果它被声明为template &lt;typename T&gt; void insert(T x);,那么template &lt;&gt; void S::insert&lt;const char*&gt;(const char*) 将适用于insert("")
    • 是的,当然,谢谢。出于好奇(并且没有删除主模板中的引用):这甚至适用于尝试部分专业化模板“hacks”和明确使用std::decay(/std::enable_if)? (我自己也自然地尝试过,但没有成功)。
    猜你喜欢
    • 2020-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多