Array to pointer class 模板参数推导适用于模板指南,但不适用于非模板版本,这是正确的还是错误?

Array to pointer class template argument deduction works for template guide, but not for non template version, is that correct or bug?

我有 class 具有单一类型参数和 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

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

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

您的第二个推导指南有效,因为此处 T 被推导为 const char,这完全没问题。

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

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

会给你预期的结果。