【问题标题】:Array to pointer class template argument deduction works for template guide, but not for non template version, is that correct or bug?数组到指针类模板参数推导适用于模板指南,但不适用于非模板版本,这是正确的还是错误的?
【发布时间】:2018-05-30 14:56:30
【问题描述】:

我有具有单一类型参数和const char* 类型完全专业化的类模板,简化示例如下:

template <typename T>
struct PrettyPrint {
    PrettyPrint(const T& value) : value(value) {}
    const T& value;
    friend std::ostream& operator << (std::ostream& os, const PrettyPrint& pp) {
        return os << "(" << pp.value << ")";
    }
};
template <>
struct PrettyPrint<const char*> {
    PrettyPrint(const char* value) : value(value) {}
    const char* value;
    friend std::ostream& operator << (std::ostream& os, const PrettyPrint& pp) {
        return os << "\"" << pp.value << "\"";
    }
};

简而言之 - 打印像 "abc" 这样的字符字符串和像 (123) 这样的所有其他值("" vs ()

因此,我添加了一个演绎指南,以替代所有 char[N] 类型的额外偏特化:

template <std::size_t N>
PrettyPrint(char(&)[N]) -> PrettyPrint<const char*>; //deduction guide

不幸的是它不起作用:

 std::cout << PrettyPrint(7) << PrettyPrint("aaa") << PrettyPrint((const char*)"bbb");

(7)(aaa)"bbb"

预期输出:

(7)"aaa""bbb"

但是,令人惊讶的是,这是可行的:

template <typename T, std::size_t N>
PrettyPrinter(T(&)[N]) -> PrettyPrinter<const T*>; //deduction guide

 std::cout << PrettyPrint(7) << PrettyPrint("aaa") << PrettyPrint((const char*)"bbb");

(7)"aaa""bbb"

所以问题:

  1. 这是正确的(那么为什么)或者这是编译器中的错误(使用 gcc/clang 测试 - 最新版本)
  2. 如果正确 - 那么如何将此模板扣除指南限制为仅限char

【问题讨论】:

    标签: c++ c++17 template-argument-deduction


    【解决方案1】:

    这是意料之中的。字符串文字的类型为const char[N]。注意const。 const 值不能绑定到非 const 引用,因此实际上没有选择您的推导指南,而是将主模板实例化。

    template <std::size_t N>
    PrettyPrint(const char(&)[N]) -> PrettyPrint<const char*>;
    

    您的第二个推导指南有效,因为在这里,T 被推导出为 const char,这非常好。

    【讨论】:

      【解决方案2】:

      这里的问题是字符串文字是const char[N],而不是char[N]。将指南更改为

      template <std::size_t N>
      PrettyPrint(const char(&)[N]) -> PrettyPrint<const char*>; //deduction guide
      

      会给你预期的结果。

      【讨论】:

      • 它有效,只是为了解释我自己-我用这个技巧检查了template &lt;typename T&gt; class WhatIsT; WhatIsT&lt;decltype(PrettyPrint("aa"))&gt; dummy;,它给了我“未定义模板'WhatIsT>'的隐式实例化”-注意@ 987654325@ - 不是const char[3]) ...所以我尝试了char[N] ...谢谢。
      • @PiotrNycz 那是因为你的构造函数需要一个const T&amp;,所以不需要推断const,因为它已经存在了:D
      • @Rakete1111 你认为我应该在我的通用模板版本中使用T&amp;&amp;,比如PrettyPrint(T&amp;&amp; value) : value(std::forward&lt;T&gt;(value)) {} T&amp;&amp; value; 。它有效 - 但我不确定。
      • @PiotrNycz 不能说。我也看不出两者之间有什么区别,所以我想说什么就说什么:)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-22
      相关资源
      最近更新 更多