оператор Friend << класса шаблона, с дополнительным параметром шаблона по умолчанию - PullRequest
0 голосов
/ 03 февраля 2020

В следующем коде A является классом шаблона, в зависимости от нетипичного параметра bool type. Друг operator<< определен для A<true> и A<false>. operator<< дополнительно зависит от другого параметра шаблона bool.

#include <ostream>
#include <iostream>
#include <type_traits>

template <bool type>
class A;

template <>
class A<true> {
    int m_x;
public:
    A(int x) : m_x{x} { }
    template <bool d, bool type>
    friend std::ostream& operator<<(std::ostream& os, const A<type>& a);
};

template <>
class A<false> {
    int m_y;
public:
    A(int y) : m_y{y} { }
    template <bool d, bool type>
    friend std::ostream& operator<<(std::ostream& os, const A<type>& a);
};

template <bool d, bool type>
std::ostream& operator<<(std::ostream& os, const A<type>& a)
{
    if constexpr (type) {
        os << "m_x = " << a.m_x << std::endl;
        if constexpr (d) { os << "2m_x = " << a.m_x << std::endl; }
    }
    else {
        os << "m_y = " << a.m_y << std::endl;
        if constexpr (d) { os << "2m_y = " << a.m_y << std::endl; }
    }
    return os;
}


int main()
{
    A<true> atrue{2};
    A<false> afalse{3};

    operator<< <true>(std::cout, atrue);
    operator<< <false>(std::cout, atrue);

    operator<< <true>(std::cout, afalse);
    operator<< <false>(std::cout, afalse);

    return 0;
}

См. в прямом эфире на Coliru .

Теперь я хотел бы указать значение по умолчанию: параметр шаблона d из operator<<, скажем d=false такой, что этот оператор

std::cout << atrue;

эквивалентен

operator<< <false>(std::cout, atrue);

, поскольку bool d принимает значение по умолчанию d=false и bool type выводится из второго аргумента operator<<.

Существует ли синтаксис, позволяющий это сделать?

Если я вставлю параметр по умолчанию в объявление друга

template <bool d = false, bool type>
friend std::ostream& operator<<(std::ostream& os, const A<type>& a);

Я получаю ошибку компиляции:

main. cpp: 14: 71: ошибка: аргументы шаблона по умолчанию не могут использоваться в объявлениях друзей шаблона

Если я вставлю параметр по умолчанию в код operator<<

template <bool d = false, bool type>
std::ostream& operator<<(std::ostream& os, const A<type>& a)
{
...

снова, он не скомпилируется, выдав ошибку

main. cpp: 27: 15 : ошибка: переопределение друга 'template std :: ostream & operator << (std :: ostream &, const A &)' может не иметь аргументов шаблона по умолчанию * 1 047 * <p>27 | std :: ostream & operator << (std :: ostream & os, const A & a) </p>

main. cpp: 14: 26: примечание: 'шаблон std :: ostream & operator << (std :: ostream & , const A &) 'ранее заявлено здесь </p>

14 | друг std :: ostream & operator << (std :: ostream & os, const A & a); </p>

1 Ответ

1 голос
/ 03 февраля 2020

ОК, на самом деле решение было относительно простым. Достаточно добавить объявление шаблона operator<< перед специализациями классов:

template <bool type>
class A;

template <bool d = false, bool type>
std::ostream& operator<<(std::ostream& os, const A<type>& a);
....

Таким образом, объявление friend внутри A<type> не объявляет operator<< в первую очередь, но только заявляет, что это friend. Рабочий пример можно проверить здесь .

...