Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> передача параметров функции в шаблон в c++11 
V
    Опции темы
Ivan.
Дата 6.9.2012, 14:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 291
Регистрация: 2.11.2004

Репутация: 1
Всего: 2



Здравствуйте, вопрос в следующем:
Почему нельзя передать параметры функции в качестве аргументов шаблона, если эта функция constexpr
Пример:
Код

template<int ...list> struct SSS{static const int v = 0;};
template<typename ...Types> constexpr int Func(Types ...List){
  return SSS<List...>::v;
}

Почему List... не является константой, если вся функция constexpr?


--------------------
Я могу ВСЁ, вопрос - сколько времени у меня это займет!
PM MAIL ICQ   Вверх
bsa
Дата 6.9.2012, 15:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



Замени 'static const int v = 0;' на enum { v = 0 };
PM   Вверх
Ivan.
Дата 6.9.2012, 17:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 291
Регистрация: 2.11.2004

Репутация: 1
Всего: 2



дело не в static const - это я просто упростил пример, на самом деле там идет рекурсивный темплейт.
он не может передать входные параметры в качестве параметров темплейта.
он пишет: 'List#1' is not a constant expression. в функцию можно передать все что угодно, в том числе и в рантайме и строить на этом этапе темплейт уже поздно. но я помечаю, что вся функция является константой и должна выполняться на этапе компиляции, но компилятор этого не понимает. я и хочу спросить, как можно объяснить компилятору, что входные параметры являются константами?


--------------------
Я могу ВСЁ, вопрос - сколько времени у меня это займет!
PM MAIL ICQ   Вверх
boostcoder
Дата 6.9.2012, 17:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



покажи компилябельный код воспроизводящий ошибку.

PM WWW   Вверх
Ivan.
Дата 6.9.2012, 18:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 291
Регистрация: 2.11.2004

Репутация: 1
Всего: 2



Код

template<typename T,      T ...List>struct _SFlags; //Декларация шаблона
template<typename T, T b, T ...List>struct _SFlags<T, b, List...>{static const long long v = (1LL << b) | _SFlags<T, List...>::v;}; //Рекурсив, пока не кончатся аргументы
template<typename T                >struct _SFlags<T            >{static const long long v = 0;}; //Начальное значение при отсутствии аргументов
template<typename T, T Max>
class SFlags
{
    long long Flags; //Массив флагов
public:
    template<typename ...Types>constexpr SFlags(Types ...List) :Flags(_SFlags<T, List...>::v){} //Конструктор неограниченного числа аргументов
};
enum EErrors {eBreakSensor1, eBreakSensor2, wMinPressure, eMaxTemperature, eCOUNT};
typedef SFlags<EErrors, eCOUNT> TError;
const TError BreakError(eBreakSensor1, eBreakSensor2, eMaxTemperature);

задача в следующем: есть такой шаблонный класс битов типа TSet, на основе его создаются классы перечня ошибок и др. он естественно имеет всякие методы.
так вот, мне нужно создать объект типа TError с какими то предустановленными битами, указанными в конструкторе. вот этот конструктор я и пытаюсь написать.
шаблон _SFlags объединяет биты на основе списка аргументов и сохраняет их в статическую переменную.
конструктор класса SFlags сохраняет в поле Flags значение v шаблона _SFlags передавая туда входные аргументы конструктора.
Конструктор SFlags обязательно должен быть constexpr, чтобы разместить данные в кодовой памяти при компиляции.

Это сообщение отредактировал(а) Ivan. - 6.9.2012, 18:35


--------------------
Я могу ВСЁ, вопрос - сколько времени у меня это займет!
PM MAIL ICQ   Вверх
boostcoder
Дата 6.9.2012, 18:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



это не совсем то, чего я ожидал.
добавь main(), добавь пример использования...

Добавлено через 1 минуту и 8 секунд
и кто такие eBreakSensor2, eMaxTemperature ?
как этот код может называться компилябельным?
PM WWW   Вверх
Ivan.
Дата 6.9.2012, 19:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 291
Регистрация: 2.11.2004

Репутация: 1
Всего: 2



я пишу системы автоматического управления различных протекающих процессов в основном для контроллеров.
eBreakSensor1, eBreakSensor2, wMinPressure, eMaxTemperature - это перечень каких либо флагов, в частности аварий и предупреждений в системе.
eBreakSensor1 - обрыв датчика 1;
eBreakSensor2 - обрыв датчика 2;
wMinPressure - предупреждение минимального давления;
eMaxTemperature - авария по максимальной температуре;
eCOUNT - число флагов в енуме.
Код

template<typename T,      T ...List>struct _SFlags;
template<typename T, T b, T ...List>struct _SFlags<T, b, List...>{static const long long v = (1LL << b) | _SFlags<T, List...>::v;};
template<typename T                >struct _SFlags<T            >{static const long long v = 0;};
template <typename T, T Max>
class SFlags
{
    long long Flags;
public:
    template<typename ...Types>constexpr SFlags(Types ...List) :Flags(_SFlags<T, List...>::v){}
    //методы:
    inline bool operator &(const SFlags<T, Max>& Value) {return (Flags & Value.Flags) != 0;}
};
enum EErrors {eBreakSensor1, eBreakSensor2, wMinPressure, eMaxTemperature, eCOUNT};
typedef SFlags<EErrors, eCOUNT> TError;
const TError PROGMEM SensorErrors(eBreakSensor1, eBreakSensor2);
const TError PROGMEM AllErrors(eBreakSensor1, eBreakSensor2, eMaxTemperature);
const TError PROGMEM AllWarnings(wMinPressure);
//---------------------------------------------------------------------------
int main()
{
    while (1){
        if (Errors & AllErrors){ //Если среди текущих аварий есть хоть одна авария перечисленная в переменной AllErrors
            puts("Авария"); //Выводим аварию и зависаем
            while (1){}
        }
        if (Errors & AllWarnings){ //Если есть хоть один флаг предупреждения
            puts("Предупреждение"); //Выводим предупреждающее сообщение
        }
    }
}


Добавлено @ 19:11
забыл, еще есть такая переменная текущих флагов ошибок: TError Errors; куда помещаются текущее состояние системы. я не буду описывать всю систему, откуда они берутся и как туда попадают

Это сообщение отредактировал(а) Ivan. - 6.9.2012, 19:13


--------------------
Я могу ВСЁ, вопрос - сколько времени у меня это займет!
PM MAIL ICQ   Вверх
Ivan.
Дата 6.9.2012, 20:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 291
Регистрация: 2.11.2004

Репутация: 1
Всего: 2



решил!!! заменил рекурсивную структуру на рекурсивную функцию:
Код

template<typename ...Types>constexpr long long _SFlags(Types ...List); //декларация шаблонной функции
template<typename T, typename ...Types>constexpr long long _SFlags(T b, Types ...List){return (1LL << b) | _SFlags(List...);} //Рекурсия, пока не останется 1 аргумент
template<typename T>constexpr long long _SFlags(T b){return 1LL << b;} //значение при единственном агрументе
class SFlags
{
public:
    long long Flags;
    template<typename ...Types>constexpr SFlags(Types ...List) :Flags(_SFlags(List...)){}
};

Вывод: в шаблон можно загонять только типы, и чистые данные базовых типов и енумов без каких либо преобразований (int)Value, где Value является long, и значений, возвращаемых какими либо функциями, даже если они constexpr.

Это сообщение отредактировал(а) Ivan. - 6.9.2012, 20:19


--------------------
Я могу ВСЁ, вопрос - сколько времени у меня это займет!
PM MAIL ICQ   Вверх
Ivan.
Дата 7.9.2012, 10:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 291
Регистрация: 2.11.2004

Репутация: 1
Всего: 2



Беда. получилась следующая аказия: в классе появился конструктор с неопределенным числом неопределенного типа аргументов.
Задача. необходимо создать копию объекта, что мы делаем:
Код
TError Error(eBreakSensor1, eBreakSensor2); //Первый экземпляр класса TError;
//Создаем копию
TError E1 = Error;

Что делает компилятор: 
- видит доступный конструктор с неограниченным числом аргументов - тип подходит, количество аргументов тоже;
- входит в него;
- встречает операцию 1LL << Value, где Value является типом TError;
- пытается его к чему нибуть преобразовать, чтобы получить число;
- встречает оператор bool() - пойдет;
- в итоге вместо копии происходит инициализация массива битов установкой первого бита.
Выход: создать конструктор копии
Код
constexpr TFlags(const TFlags &Value) :Flags(Value.Flags){}

это все хорошо, но что делать, если поле Flags не long long, а массив char?
Код
template<u8 Size>
struct TFlags {
  u8 Flags[Size];
  constexpr TFlags(const TFlags &Value) :Flags(Value.Flags){} //Косяк Flags - это массив, а Value.Flags - указатель
};

Копировать через цикл - не хорошо.
Вопрос, как можно проинициализировать массив?


--------------------
Я могу ВСЁ, вопрос - сколько времени у меня это займет!
PM MAIL ICQ   Вверх
bsa
Дата 7.9.2012, 12:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



в С++11 кажется есть возможность использовать дефолтовый конструктор: 
Код
class MyClass {
  MyClass(const MyClass &other) = default;
};
Я ошибаюсь?
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0554 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.