Форум программистов, компьютерный форум, киберфорум
Наши страницы

C++

Войти
Регистрация
Восстановить пароль
 
Kastaneda
Jesus loves me
Эксперт С++
4689 / 2893 / 236
Регистрация: 12.12.2009
Сообщений: 7,357
Записей в блоге: 2
Завершенные тесты: 1
#1

Создать список ф-ций определяемых в файле (а-ля initializer list) в compile time - C++

29.12.2015, 07:33. Просмотров 445. Ответов 9
Метки нет (Все метки)

Привет!

Хочу как-то регистрировать все ф-ции, объявляемые в файле, например есть вот это

C++
1
2
3
std::string f1() { return "asdf1"; }
std::string f2() { return "asdf2"; }
std::string f3() { return "asdf3"; }
хотелось бы в конце файла иметь список
C++
1
{f1(), f2(), f3()}
Если точнее, то хочу использовать это так
C++
1
2
3
4
std::vector<std::string> registered_values()
{
    return { f1(), f2(), f3() };
}
Пока тело registered_values() прихоится руками поддерживать, вот хочется автоматизировать.
Я плохо умею обращаться с шаблонными фишками С++11, поэтому даже не уверен, что такое возможно. Понятно, что каждая f1, f2, ... будет структурой с оператором (), которая будет наследовать что-то, где будет вся магия. Может кто-то сможет это сделать?
Вопрос скорее любопытства ради, но если получится, то вставлю в проект
0
Лучшие ответы (1)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
29.12.2015, 07:33
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Создать список ф-ций определяемых в файле (а-ля initializer list) в compile time (C++):

Compile-time алгоритмы. сборник - C++
всем привет. предлагаю в этой теме обсуждать/реализовывать/выкладывать compile-time алгоритмы. под CUT'ом. подсчет FNV1a-хеш суммы...

Что такое compile-time алгоритмы и для чего они нужны? - C++
А есть от них хоть какая-то практическая польза? По-моему нет

Compile-time и run-time методы и функции - C++
Добрый день. Есть две функции, которые делают идентичную работу: template&lt;bool leftShift, typename T&gt; T byteShift(T data) { ...

Compile - time алгоритмы - C++
мне итересно, с появлением constexpr надобность в шаблонных компиле-тайм алгоритмах полностью отпала?..)

Выделение памяти объёмом, известном в compile-time - C++
Правда ли, что, скажем new int Произойдёт существенно быстрее, чем int length = runtimeComputeLength(); // returns 1000 new int;

Const в delay.h: compile time integer constant - C (Си)
Есть такая библиотека, delay.h. В ней есть функция _delay_us(double __us): _delay_us(double __us) { double __tmp ; #if...

9
hoggy
6703 / 2885 / 494
Регистрация: 15.11.2014
Сообщений: 6,485
Завершенные тесты: 1
29.12.2015, 22:40 #2
Цитата Сообщение от Kastaneda Посмотреть сообщение
Пока тело registered_values() прихоится руками поддерживать, вот хочется автоматизировать.
смысли автоматизировать?
вам в любом случае придется указать имя функции,
которую нужно будет пинать.

и сделать это можно только в ручную.

я хочу сказать, нет разницы:
в ручную вбить очередное имя в теле функции,
или вручную вбить это же имя где нибудь в параметре шаблона.

все равно вбивать придется вручную.
0
DrOffset
7376 / 4453 / 1009
Регистрация: 30.01.2014
Сообщений: 7,304
29.12.2015, 23:13 #3
Kastaneda, в общем, вот такая вот наркомания:
Кликните здесь для просмотра всего текста

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#include <iostream>
#include <cstdint>
#include <vector>
#include <algorithm>
 
constexpr uint32_t ct_hash_suffix(char c, size_t seed)
{
    return static_cast<uint32_t>(c) + uint32_t(0x9e3779b9) + (seed << 6) + (seed >> 2);
}
 
uint32_t hash_value(std::string const & str)
{
    uint32_t seed = 0;
    for(char c : str)
    {
        seed ^= ct_hash_suffix(c, seed);
    }
    return seed;
}
 
constexpr uint32_t ct_hash(char const * str, uint32_t seed = 0)
{
    return *str ? ct_hash(str + 1, seed ^ ct_hash_suffix(*str, seed)) : seed;
}
 
template <uint32_t File, typename F>
class FunctionStorage
{
    template <typename FS>
    struct ResultOf;
 
    template <typename R, typename ...A>
    struct ResultOf<R(A...)>
    {
        using type = R;
    };
 
    using RetType = typename ResultOf<F>::type;
 
    struct Caller
    {
        RetType operator()(F f) const
        {
            return f();
        }
    };
 
public:
    static FunctionStorage & instance()
    {
        static FunctionStorage inst;
        return inst;
    }
 
    F * add(F * func)
    {
        m_funcs.push_back(func);
        return func;
    }
 
    F * operator[](size_t idx)
    {
        return m_funcs[idx];
    }
 
    std::vector<RetType> callAll() const
    {
        std::vector<RetType> ret(m_funcs.size());
        std::transform(m_funcs.begin(), m_funcs.end(), ret.begin(), Caller());
        return ret;
    }
 
private:
    std::vector<F *> m_funcs;
};
 
template <uint32_t File, typename FuncType>
class FunctionRegister
{
public:
    FunctionRegister(FuncType * f)
        : m_func(FunctionStorage<File, FuncType>::instance().add(f))
    { }
 
    FuncType * operator~() const
    { return m_func; }
 
private:
    FuncType * m_func;
};
 
#define REGISTERED_VALUES() \
    FunctionStorage<ct_hash(__FILE__), std::string()>::instance().callAll()
 
#define FUNCTION_DECL(F) \
    std::string(*F)() = ~(FunctionRegister<ct_hash(__FILE__), std::string()>)[]
 
 
/* Функции определяем так: */
FUNCTION_DECL(a)() -> std::string
{
    return "a";
};
FUNCTION_DECL(b)() -> std::string
{
    return "b";
};
 
int main()
{
   /* в зависимости от места вызова будет давать разные результаты
       например, для файла с функциями a.cpp будет один список, для файла b.cpp - другой.
       можно добавить еще один вариант, который принимает имя файла в качестве параметра
       тогда можно будет запрашивать списки, задавая нужный файл
   */
    auto v = REGISTERED_VALUES();
 
    for(auto & c : v)
        std::cout << c << std::endl;
}
http://rextester.com/QTPEI24794
Ни в коем случае не законченное решение, а скорее эксперимент. Но продолжать мне лень, но есть пара мыслей.
Что здесь плохо:
1) Хэш времени компиляции ненадежен. Можно заменить на полноценные compile-time строки в качестве уникального тега файла, но код станет более сложным и пример перестанет быть демонстрационным. В любом случае, если интересно, то могу поделиться своими наработками в этой области.
2) Даже со строками вместо хешей, будут коллизии в общем случае. Т.к. файлы в проекте теоретически могут называться одинаково. Я считаю, что на общий случай распространить решение не получится.
3) Функции на самом деле не функции, а указатели на функции, следовательно могут возникнуть проблемы при необходимости использовании внешнего связывания (как вариант, можно воспользоваться сишным приемом "extern указатель на функцию", для использования в других единицах трансляции).
4) std::vector внутри хранилища зарегистрированных функций. Пока что не вижу разумных вариантов этого избежать.
5) Невозможность обобщить решение на любые функции: с любым количеством параметров и типов возвращаемого значения. Для этого скорее всего придется что-то сильно менять, текущий вариант этого не позволит в полной мере.

В любом случае, баловаться таким в реальных проектах я бы не советовал.
Это же ужас что. Кто потом это будет поддерживать?!
Однако, возможно какие-то идеи окажутся полезными и ты решишь написать свой вариант на базе них, который будет более соответствовать задаче (более узкоспециализированным) и окажется более безопасным и простым из-за этого.
4
Kastaneda
Jesus loves me
Эксперт С++
4689 / 2893 / 236
Регистрация: 12.12.2009
Сообщений: 7,357
Записей в блоге: 2
Завершенные тесты: 1
30.12.2015, 06:09  [ТС] #4
Цитата Сообщение от hoggy Посмотреть сообщение
я хочу сказать, нет разницы:
в ручную вбить очередное имя в теле функции,
или вручную вбить это же имя где нибудь в параметре шаблона.
Есть разница. Вот что я имею ввиду - хочу добавить новую ф-цию, добавляю
C++
1
2
3
4
std::string f123()
{
    return "asdf123";
}
при этом я (или другой программист) должен не забыть добавить ее в другую ф-цию.
C++
1
2
3
4
std::vector<std::string> registered_values()
{
    return { f1(), f2(), f3(), ..., f123() };
}
Т.е. добавление чего-то одного требует правки в двух местах. Это не есть гуд, очевидно, что кто-нибудь когда-нибудь забудет.

DrOffset, спасибо, чуть позже поразбираюсь.
0
ForEveR
В астрале
Эксперт С++
7983 / 4742 / 321
Регистрация: 24.06.2010
Сообщений: 10,545
Завершенные тесты: 3
30.12.2015, 10:19 #5
DrOffset, Шикарно.
Цитата Сообщение от DrOffset Посмотреть сообщение
1) Хэш времени компиляции ненадежен. Можно заменить на полноценные compile-time строки в качестве уникального тега файла, но код станет более сложным и пример перестанет быть демонстрационным. В любом случае, если интересно, то могу поделиться своими наработками в этой области.
Интересно, если есть возможность, было бы очень интересно увидеть.
0
Kastaneda
Jesus loves me
Эксперт С++
4689 / 2893 / 236
Регистрация: 12.12.2009
Сообщений: 7,357
Записей в блоге: 2
Завершенные тесты: 1
30.12.2015, 10:40  [ТС] #6
Да, посмотрел, круто получилось!
Сам еще тоже немного посидел на этим делом, хотел что-то принципиально другое сделать. Сначал с бустовским препроцессором полчаса просидел, может и можно сделать, но за полчаса не осилил, потом еще с полчаса хотел сам что-то сваять через шаблоны.
В итоге потратил час рабочего времени на задачу, которая даже не нужна (без нее все работает), вернулся обратно к работе).
0
DrOffset
7376 / 4453 / 1009
Регистрация: 30.01.2014
Сообщений: 7,304
31.12.2015, 01:23 #7
Лучший ответ Сообщение было отмечено автором темы, экспертом или модератором как ответ
Цитата Сообщение от ForEveR Посмотреть сообщение
было бы очень интересно увидеть.
Публиковал относительно недавно на другом российском форуме. Вариация на тему compile-time механизма перевода приложения.
С++11 (в С++14 будет чуть поменьше кода)
ct_string.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#ifndef CT_STRING_H_INCLUDED
#define CT_STRING_H_INCLUDED
 
namespace ct
{
 
template <char ...Chars>
struct string
{
    enum { length = sizeof...(Chars) - 1 };
 
    static char const value[];
};
 
template <char ...Chars>
char const string<Chars...>::value[] = { Chars... };
 
} // ct
 
#endif // CT_STRING_H_INCLUDED

ct_indices_utils.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#ifndef CT_INDICES_UTILS_H_INCLUDED
#define CT_INDICES_UTILS_H_INCLUDED
 
#include <cstddef>
 
namespace ct
{
 
template <size_t ...I>
struct indices
{ };
 
template <size_t Max, size_t ...Indices>
struct make_indices
    : make_indices<Max - 1, Max - 1, Indices...>
{ };
 
template <size_t ...Indices>
struct make_indices<0, Indices...>
    : indices<Indices...>
{
    using type = indices<Indices...>;
};
 
} // ct
 
#endif // CT_INDICES_UTILS_H_INCLUDED

ct_string_utils.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#ifndef CT_STRING_UTILS_H_INCLUDED
#define CT_STRING_UTILS_H_INCLUDED
 
#include "ct_string.h"
#include "ct_indices_utils.h"
 
namespace ct
{
 
template <typename Str, typename I>
struct string_gen;
 
template <typename Str, size_t ...I>
struct string_gen<Str, ::ct::indices<I...>>
    : ::ct::string<Str{}.chars[I]...>
{ };
 
template <typename Str, size_t Len>
struct make_string
    : string_gen<Str, typename ::ct::make_indices<Len>::type>
{ };
 
} // ct
 
#endif // CT_STRING_UTILS_H_INCLUDED

translator.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#ifndef TRANSLATOR_H_INCLUDED
#define TRANSLATOR_H_INCLUDED
 
#include "ct_string.h"
#include "ct_indices_utils.h"
#include "ct_string_utils.h"
 
class Translator
{
public:
    enum { LangMax = 5 };
 
    struct Holder
    {
        char const * m_strings[LangMax];
    };
 
private:
    template <typename Value>
    struct Storage : Value, Holder
    {
        template <size_t ...I>
        Storage(Translator & self, ct::indices<I...>)
            : Holder{ { ((void)I, Value::value)... } }
        { }
 
        explicit Storage(Translator & self)
            : Storage(self, ct::make_indices<LangMax> {})
        { }
    };
 
    template <char ...Chars>
    Holder * addString(ct::string<Chars...> const &)
    {
        static Storage<ct::string<Chars...>> s(*this);
        return &s;
    }
 
public:
    static Translator & instance()
    {
        static Translator inst;
        return inst;
    }
 
    template <typename Original, typename Translated>
    void addTranslation(size_t lang)
    {
        Holder * h = this->addString(Original{});
        h->m_strings[lang] = Translated::value;
    }
    template <typename Original>
    char const * addString()
    {
        Holder * h = this->addString(Original{});
        return h->m_strings[m_lang];
    }
 
    static void setLang(size_t lang)
    {
        instance().m_lang = lang;
    }
 
private:
    size_t m_lang = 0;
};
 
#define TR(str) []() \
    {                                                                   \
        struct StringType1 { const char * chars = (str); };             \
        using type1 = ::ct::make_string<StringType1, sizeof((str))>;    \
        return Translator::instance().addString<type1>();               \
    }()
 
#define SETUP_TR(lang, orig, trans) []() \
    {                                                                   \
        struct StringType1 { const char * chars = (orig);  };           \
        using type1 = ::ct::make_string<StringType1, sizeof((orig))>;   \
        struct StringType2 { const char * chars = (trans); };           \
        using type2 = ::ct::make_string<StringType2, sizeof((trans))>;  \
        Translator::instance().addTranslation<type1, type2>(lang);      \
        return true;                                                    \
    }()
 
#endif // TRANSLATOR_H_INCLUDED

Использование:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <cstdio>
 
#include "translator.h"
 
enum { RUS = 1 };
 
namespace {
bool f1 = SETUP_TR(RUS, "start", "старт");
bool f2 = SETUP_TR(RUS, "text", "текст");
}
 
int main()
{
    Translator::setLang(RUS);
 
    std::printf("%s\n", TR("start"));
    std::printf("%s\n", TR("start"));
    std::printf("%s\n", TR("text"));
}
http://rextester.com/WYUMS67445

Добавлено через 11 часов 16 минут
Kastaneda, в общем выдалась свободная минутка, и я слегка улучшил первоначальный код и избавился от некоторых проблем.
Нужен C++14, но можно и без него, просто мне уже не очень охота переделывать.
Итак, сперва чего удалось достичь:
1) Теперь нет глобальных переменных-указателей, вместо этого полноценные функции (хоть и шаблонные).
2) Вследствие этого теперь возможно поместить реализацию функций в заголовочный файл. Хитрость с явным инстанцированием частичной специализации, вместо применения полной специализации позволит избежать multiple definition.
3) Избавился от вектора в качестве хранилища. Теперь там связный список на статических объектах. Куча не используется до входа в main вообще.
4) Идентификация файла через compile-time строковый тег - коллизиям говорим "нет" . Кстати, проблемы одинаковых файлов не возникнет, по крайней мере на GCC и Clang, т.к. __FILE__ там включает полное имя, а не короткое.
5) В качестве регистрируемой функции можно использовать функцию с любой(!) сигнатурой. Будет создано по отдельному хранилищу на каждый тип. Предусмотрена возможность задать нужный тип для группового вызова.

Минусы конечно тоже есть. Из основных:
- Перегрузка не поддерживается.
- Страшный синтаксис.
- Время компиляции растет.
- Функции для прямого вызова - шаблонные. Отсюда проблемы с взятием адреса такой функции, приходится указывать аргументы шаблона ну и т.п.

ct_string_v1.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#ifndef CT_STRING_V1_H_INCLUDED
#define CT_STRING_V1_H_INCLUDED
 
#include <boost/preprocessor/repetition/repeat.hpp>
#include <boost/preprocessor/punctuation/comma_if.hpp>
#include <boost/preprocessor/config/limits.hpp>
 
template <char ...Chars>
struct string
{};
 
namespace detail
{
    template <typename Res, char ...Chars>
    struct trim_zeros_impl;
 
    template <char... N, char C, char ...Chars>
    struct trim_zeros_impl<string<N...>, C, Chars...>
        : std::conditional<C
            , trim_zeros_impl<string<N..., C>, Chars...>
            , trim_zeros_impl<string<N..., 0>> // force recursion end
          >::type
    { };
 
    template <char ...Chars>
    struct trim_zeros_impl<string<Chars...>>
    {
        using type = string<Chars...>;
    };
}
template <char ...Chars>
struct trim_zeros
    : detail::trim_zeros_impl<string<>, Chars...>
{ };
 
#define STRING_TO_CHARS_BY_ONE(Z, N, STR) \
        BOOST_PP_COMMA_IF(N) N >= sizeof(STR) ? '\0' : STR[N]
 
#define STRING_TO_CHARS(LEN, STR)  \
        BOOST_PP_REPEAT(LEN, STRING_TO_CHARS_BY_ONE, STR)
 
#define MAKE_CT_STRING(STR) trim_zeros<STRING_TO_CHARS(256, STR)>::type
 
#endif // CT_STRING_V1_H_INCLUDED

func_registry.h

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#ifndef FUNC_REGISTRY_H_INCLUDED
#define FUNC_REGISTRY_H_INCLUDED
 
#include <type_traits>
#include <utility>
 
#include <vector>
#include <cstddef>
 
#include "ct_string_v1.h"
/*----------------------------------------------------------------------------*/
template <typename File, typename FType>
struct FunctionReg
{
    explicit FunctionReg(FType f);
 
    FunctionReg * next;
    FType *       call;
};
/*----------------------------------------------------------------------------*/
template <typename File, typename F>
class FunctionStorage;
 
template <typename File, typename Ret, typename ...Args>
class FunctionStorage<File, Ret(Args...)>
{
    using FuncPtrType  = Ret(*)(Args...);
    using FuncRegistry = FunctionReg<File, Ret(Args...)>;
 
    FunctionStorage()
        : m_first(), m_last(), m_len()
    {}
public:
    static FunctionStorage & instance()
    {
        static FunctionStorage inst;
        return inst;
    }
    void append(FuncRegistry * reg)
    {
        if(m_first)
        {
            m_last->next = reg;
        }
        else
        {
            m_first = reg;
        }
        m_last = reg;
        ++m_len;
    }
    std::vector<Ret> callAll(Args && ...args)
    {
        std::vector<Ret> ret(m_len);
 
        FuncRegistry * reg = m_first;
        for(size_t i = 0; reg; reg = reg->next)
        {
            ret[i++] = reg->call(std::forward<Args>(args)...);
        }
        return ret;
    }
 
private:
    FuncRegistry * m_first;
    FuncRegistry * m_last;
    size_t         m_len;
};
/*----------------------------------------------------------------------------*/
template <typename File, typename FType>
FunctionReg<File, FType>::FunctionReg(FType f)
    : next(), call(f)
{
    FunctionStorage<File, FType>::instance().append(this);
}
/*----------------------------------------------------------------------------*/
template <typename FuncName, typename FileName>
struct FunctionEntry;
/*----------------------------------------------------------------------------*/
 
#define FUNCTION_DECL(FName, Body) \
template <typename FileName> \
struct FunctionEntry<MAKE_CT_STRING(#FName), FileName>                      \
{                                                                           \
    static auto FName Body;                                                 \
private:                                                                    \
    using  FuncReg = FunctionReg<FileName, decltype(FunctionEntry::FName)>; \
    static FuncReg reg;                                                     \
}; \
\
template class FunctionEntry<MAKE_CT_STRING(#FName), MAKE_CT_STRING(__FILE__)>; \
\
template <typename FileName>                                                  \
typename FunctionEntry<MAKE_CT_STRING(#FName), FileName>::FuncReg             \
            FunctionEntry<MAKE_CT_STRING(#FName), FileName>::reg(             \
                &FunctionEntry<MAKE_CT_STRING(#FName), FileName>::FName       \
            ); \
\
template <typename ...Args>          \
inline auto FName(Args && ...args)   \
{ return FunctionEntry<              \
            MAKE_CT_STRING(#FName)   \
          , MAKE_CT_STRING(__FILE__) \
         >::FName(std::forward<Args>(args)...); \
} \
\
template <typename FileName> \
auto FunctionEntry<MAKE_CT_STRING(#FName), FileName>::FName Body
 
#define CALL_ALL(Type, ...) \
    FunctionStorage<MAKE_CT_STRING(__FILE__), Type>::instance().callAll(__VA_ARGS__)
 
#define CALL_ALL_FROM(File, Type, ...) \
    FunctionStorage<MAKE_CT_STRING(File), Type>::instance().callAll(__VA_ARGS__)
 
#endif // FUNC_REGISTRY_H_INCLUDED

Использование:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <string>
#include <cstdio>
 
#include "func_registry.h"
 
FUNCTION_DECL(test1, (int a) -> std::string)
{
    return "test1!";
}
FUNCTION_DECL(test2, (int b) -> std::string)
{
    return "test2!";
}
FUNCTION_DECL(test3, (int c) -> std::string)
{
    return "test3!";
}
FUNCTION_DECL(test4, () -> int)
{
    return 42;
}
 
int main()
{
    auto v = CALL_ALL(std::string(int), 1);
    for(auto & c : v)
        std::printf("%s\n", c.c_str());
 
    auto l = CALL_ALL(int());
    for(auto & c : l)
        std::printf("%d\n", c);
}
Онлайн пример: http://rextester.com/QOF3281
4
Kastaneda
Jesus loves me
Эксперт С++
4689 / 2893 / 236
Регистрация: 12.12.2009
Сообщений: 7,357
Записей в блоге: 2
Завершенные тесты: 1
31.12.2015, 05:59  [ТС] #8
DrOffset, спасибо, разберу на досуге.

Не по теме:

Вчера тему перенесли в "С++ для экспертов", сегодня обратно. Постучись в группу, должны принять.

0
ForEveR
В астрале
Эксперт С++
7983 / 4742 / 321
Регистрация: 24.06.2010
Сообщений: 10,545
Завершенные тесты: 3
31.12.2015, 11:32 #9
Kastaneda,

Не по теме:

Угу, я попросил перенести обратно.


DrOffset, Это шикарно. Не думал что ты сильно увлекаешься template метапрограммированием. Спасибо что поделился.
0
DrOffset
31.12.2015, 13:59     Создать список ф-ций определяемых в файле (а-ля initializer list) в compile time
  #10

Не по теме:

Цитата Сообщение от Kastaneda Посмотреть сообщение
Постучись в группу, должны принять.
Вообще, я сознательно туда не иду


Не по теме:

Цитата Сообщение от ForEveR Посмотреть сообщение
Не думал что ты сильно увлекаешься template метапрограммированием.
Нельзя сказать, что сильно увлекаюсь. По работе (как собственно и С++11/14) не использую, только вот в таких вот задачках.

0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
31.12.2015, 13:59
Привет! Вот еще темы с ответами:

Ошибка C2552: non-aggregates cannot be initialized with initializer list - C++
помогите пожалуйста: struct sAccInt { Account AccFrom; Account AccTo; sAccInt() : AccFrom(0L), AccTo(0L) ...

Ошибка: error: cannot convert '<brace-enclosed initializer list>' to 'int - C++
всем привет! не могу разобраться, что это за ошибка void sum_element() { const int size = 10; int arr = {0}; int...

Как использовать значения из *.properties файлов без Java кода (в compile time) - Java
Привет! Видел в других проектах подобное использование #файл my.properties user.name = UserName user.pass = UserPass далее,...

Создать циклический список list - C++
Доброго времени суток. подскажите как list сделать циклическим. допустим у нас есть list &lt;int&gt; l состоящий из 10 элементов. Нам...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
10
31.12.2015, 13:59
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru