Вычисление аргумента шаблона класса-указателя работает для руководства по шаблону, но не для не шаблонной версии, это правильно или ошибка? - PullRequest
0 голосов
/ 30 мая 2018

У меня есть шаблон класса с параметром одного типа и полной специализацией типа 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) ("" против ())

Итак, я добавил в качестве замены дополнительной частичной специализации для всех типов 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 голосов
/ 30 мая 2018

Проблема здесь в том, что строковый литерал - const char[N], а не char[N].Если изменить руководство на

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

, вы получите ожидаемые результаты.

0 голосов
/ 30 мая 2018

Это ожидается.Строковый литерал имеет тип const char[N].Обратите внимание на const.Константное значение не может быть привязано к неконстантной ссылке, поэтому ваше руководство по выводам фактически не выбрано, а вместо этого создается экземпляр основного шаблона.

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

Ваше второе руководство по выводам работает, потому что здесь выводится Tбыть const char, что совершенно нормально.

...