数组到指针类模板参数推导适用于模板指南,但不适用于非模板版本,是正确还是错误?

时间:2018-05-30 14:56:30

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

我有单一类型参数的类模板和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

2 个答案:

答案 0 :(得分:7)

这是预期的。字符串文字的类型为const char[N]。请注意const。 const值不能绑定到非const引用,因此实际上不会选择您的演绎指南,而是实例化主模板。

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

您的第二个扣除指南有效,因为此处T推断为const char,这非常好。

答案 1 :(得分:7)

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

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

会给你预期的结果。