Подскажите в чем ошибка при реализации следующей ситуации:
Есть 2 класса дробей, сущность которых идентична за исключением некоторых особенностей, зависящих от флага "сократимые дроби"/"не сократимые дроби". По умолчанию дроби сократимые, поэтому класс задаю так:
template <bool isReduced = false>
class CFraction
{
public:
int m_numenator;
int m_denumenator;
public:
// конструкторы
template <bool isReduced = false>
CFraction()
: m_numenator(0), m_denumenator(1)
{}
template <bool isReduced = false>
CFraction(const int numenator)
: m_numenator(numenator), m_denumenator(1)
{}
template <bool isReduced = false>
CFraction(const int numenator, const int denumenator)
: m_numenator(numenator), m_denumenator(denumenator)
{}
};
во первых при попытке
const CFraction num(1, 3);
сразу выдаётся ошибка
Error C2955 'CFraction': use of class template requires template argument list fractions
Error C2514 'CFraction': class has no constructors fractions
Почему так?
И второй вопрос - для сравнения использую такой код (код работал, но потом я как раз стал переходить на шаблоны :))
template <bool isReduced = false>
friend bool operator == (const CFraction& val1, const CFraction& val2)
{
return (CFraction<true>(CFraction(val1) - CFraction(val2)).m_numenator == 0);
}
тут вопрос такой - а как показать в параметрах метода, что параметр шаблона у этих параметров могут быть любые, меня они не интересуют, т.е.
friend bool operator == (const CFraction<any>& val1, const CFraction<any>& val2)
иначе это будет восприниматься как isReduced = false, а этого хотелось бы избежать
Еще раз оговорю - решил делать через шаблоны, поскольку сущности дробей сократимых и несократимых одинаковы и отличия лишь в конвертации одних в другие после завершения операций
А зачем вообще у вас при конструкторах?
template <bool isReduced = false>
class CFraction
{
public:
int m_numenator;
int m_denumenator;
public:
// конструкторы
CFraction()
: m_numenator(0), m_denumenator(1)
{}
CFraction(const int numenator)
: m_numenator(numenator), m_denumenator(1)
{}
CFraction(const int numenator, const int denumenator)
: m_numenator(numenator), m_denumenator(denumenator)
{}
};
вполне достаточно.
По второй части - см. там же. Просто делаете обычный шаблонный друг
template <bool T>
friend bool operator == (const CFraction<T>& val1, const CFraction<T>& val2)
(Кстати, у вас оператор - не определен, так что тело друга пришлось упростить :))
А что до
const CFraction<> num(1, 3);
то поставьте <>, чтобы было понятно, что это шаблон. Наверное, ваш компилятор несколько староват (или вы не попросили его поддерживать последний стандарт).
"По-моему, так". (с) Пух
В дополнение к ответу @Harry:
Есть два варианта объявления и определения дружественной функции для шаблонного класса:
CFraction, а уже затем объявить его другом класса.Пример:
template<bool reduced>
class Fraction;
template<bool F>
auto operator==(const Fraction<F>& f1, const Fraction<F>& f2) -> bool;
template<bool reduced = false>
class Fraction
{
public:
friend auto operator==<reduced>(const Fraction& f1, const Fraction& f2) -> bool;
};
template<bool F>
inline auto operator==(const Fraction<F>& f1, const Fraction<F>& f2) -> bool
{
return true;
}
Обратите внимание:
friend auto operator==<reduced>(const Fraction& f1, const Fraction& f2) -> bool;,
я указал <reduced> после оператора. Таким образом мы объявляем специализацию шаблона функции, которая не является членом класса, как друга.
Сначала я выражу свое мнение относительно того, что плохо.
Во время выполнения нормальный класс должен иметь возможность изменять свои неконстантные члены, так что если дробь изначально был сокращаемым, может стать и не сокращаемым. Чтобы выразить это, лучше применить подход хранения булевского типа в конкретном классе или же воспользоваться преимуществами наследования(первый вариант предпочтительней для данного класса).
Если все же решить впользу шаблона, то это именно тот случай, для которого используется SFINAE
Апостиль в Лос-Анджелесе без лишних нервов и бумажной волокиты
Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости