Подскажите в чем ошибка при реализации следующей ситуации:
Есть 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
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
В интернете много плееров с визуализацией, но все они основаны на статичном mp3 файле, который либо лежит на сервере, либо загружается пользователемЯ...
Как отловить само событие и получить параметры поиска? Можно ли предотвратить скролл на странице в этот момент?
В таблицу на странице из БД аяксом подгружается таблица вместе с заголовками, как сделать, чтобы заголовок подгружался 1 раз, а не после каждой...
Всем добрый деньДелаю динамическую таблицу, с подгрузкой данных из jsone