Re[3]: Код V1.01
От: Andrew S Россия http://alchemy-lab.com
Дата: 12.08.04 08:46
Оценка:
__>Пока что придирки к CNameIdHolder.
__>Вы действительно считаете что такая специализация выглядит красиво ?
__>Лучше уж сделать собственный велосипед на макросах, чем городить это все, вдобавок код у вас не расширяем, т.е. если я захочу, чтобы было не 7, а 8 параметров то мне надо очень много дописывать.

Параметров и так 8, а CNameIdHolder и не должен быть расширяем — расширяем CNameId, именно его и надо менять, если надо более длинное имя. Специализация вполне красивая, хотя и не маленькая (впрочем, можно и без нее, но так экономится размер бинарника), и макрос тут тоже лучше, чем набор отдельных классов — "не плодите сущности без необходимости", их уже и так много
Имхо, главная проблема не в этом, а в том, как удобнее пользовать основные макросы, где требуется переменное число параметров + как красивее определять макросы для различного числа параметров функций.
А вообще, откровенно говоря, мне не понятна логика комитета, который не предусмотрел специализацию строковыми литералами.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[4]: Код V1.01
От: _nn_ www.nemerleweb.com
Дата: 12.08.04 08:59
Оценка:
Здравствуйте, Andrew S, Вы писали:

__>>Пока что придирки к CNameIdHolder.

__>>Вы действительно считаете что такая специализация выглядит красиво ?
__>>Лучше уж сделать собственный велосипед на макросах, чем городить это все, вдобавок код у вас не расширяем, т.е. если я захочу, чтобы было не 7, а 8 параметров то мне надо очень много дописывать.

AS>Параметров и так 8, а CNameIdHolder и не должен быть расширяем — расширяем CNameId, именно его и надо менять, если надо более длинное имя. Специализация вполне красивая, хотя и не маленькая (впрочем, можно и без нее, но так экономится размер бинарника), и макрос тут тоже лучше, чем набор отдельных классов — "не плодите сущности без необходимости", их уже и так много

AS>Имхо, главная проблема не в этом, а в том, как удобнее пользовать основные макросы, где требуется переменное число параметров + как красивее определять макросы для различного числа параметров функций.
Зато в моем варианте не требуется переписывать для каждой специализации код.

AS>А вообще, откровенно говоря, мне не понятна логика комитета, который не предусмотрел специализацию строковыми литералами.

Потому что массивом нельзя специализировать шаблон, а строки это массив символов.
Видимо реализация этого довольно сложна.

Мне кажется лучше вместо DWORD делать так :
template<
        TCHAR c0=0,
        TCHAR c1=0,
        TCHAR c2=0,
        TCHAR c3=0,
                //...
    >
class CNameIdHolderImpl
{
};


И не будет проблем с разложением DWORD.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[5]: Код V1.01
От: Andrew S Россия http://alchemy-lab.com
Дата: 12.08.04 09:30
Оценка:
__>Зато в моем варианте не требуется переписывать для каждой специализации код.

Ваш вариант вообще работать не будет, он определяет массив из 8-ми TCHAR Забудьте про эту мысль, она плохая, уверяю вас, вы РОВНЫМ счетом ничего не съэкономите, а наоборот.

AS>>А вообще, откровенно говоря, мне не понятна логика комитета, который не предусмотрел специализацию строковыми литералами.

__>Потому что массивом нельзя специализировать шаблон, а строки это массив символов.
__>Видимо реализация этого довольно сложна.

Как раз массивом специализировать шаблон можно.



TCHAR sz[] = _T("test");

template <LPCTSTR s>
struct C
{
};

С<sz> c;


А вот сроковым литералом, который имеет internal linkage и тип const TCHAR[] — нельзя.

__>Мне кажется лучше вместо DWORD делать так :

__>
__>template<
__>        TCHAR c0=0,
__>        TCHAR c1=0,
__>        TCHAR c2=0,
__>        TCHAR c3=0,
__>                //...
    >>
__>class CNameIdHolderImpl
__>{
__>};
__>


__>И не будет проблем с разложением DWORD.


Проблем и так нет, это вы их придумали А запись имени получится в 2.5 раза длиннее и еще непонятнее.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[6]: Код V1.01
От: _nn_ www.nemerleweb.com
Дата: 12.08.04 09:42
Оценка:
Здравствуйте, Andrew S, Вы писали:

__>>Зато в моем варианте не требуется переписывать для каждой специализации код.


AS>Ваш вариант вообще работать не будет, он определяет массив из 8-ми TCHAR Забудьте про эту мысль, она плохая, уверяю вас, вы РОВНЫМ счетом ничего не съэкономите, а наоборот.


AS>>>А вообще, откровенно говоря, мне не понятна логика комитета, который не предусмотрел специализацию строковыми литералами.

__>>Потому что массивом нельзя специализировать шаблон, а строки это массив символов.
__>>Видимо реализация этого довольно сложна.

AS>Как раз массивом специализировать шаблон можно.



AS>

AS>TCHAR sz[] = _T("test");

AS>template <LPCTSTR s>
AS>struct C
AS>{
AS>};

AS>С<sz> c;
AS>


AS>А вот сроковым литералом, который имеет internal linkage и тип const TCHAR[] — нельзя.

Потому что это внешняя линковка, а все что внутреняя нельзя использовать.

Зато можно сделать такое :
template<const TCHAR s>
struct x{};

#define DEF_STR(strname,str) \
 const TCHAR strname##__unique_name[] = str; \
 x<strname##__unique_name> some_type##str_name;


__>>Мне кажется лучше вместо DWORD делать так :

__>>
__>>template<
__>>        TCHAR c0=0,
__>>        TCHAR c1=0,
__>>        TCHAR c2=0,
__>>        TCHAR c3=0,
__>>                //...
    >>>
__>>class CNameIdHolderImpl
__>>{
__>>};
__>>


__>>И не будет проблем с разложением DWORD.


AS>Проблем и так нет, это вы их придумали А запись имени получится в 2.5 раза длиннее и еще непонятнее.

Я люблю придумывать проблемы и героически их решать

Или может лучше сделать через Traits ?

template<typename TTraits>
class x;

struct traits_kernel32_lib
{ static LPCTSTR get_name() { return "kernel32.lib" } };

x<traits_kernel32_lib> lib_kernel;

Или оформить в виде макроса.
Тогда нет проблем со строкой и нет проблем с разбором строки и нет проблем с глобальной переменной.

#define USE_MODULE_BEGIN(nmspace, id, NameId) \
namespace nmspace \
{\
    struct nmspace##_traits##id##__unique_name
    { static LPCTSTR get_name() { return NameId; } };
    typedef CModule< CNameId< nmspace##_traits##id##__unique_name > > module_type;\


Ну или что-то вроде того
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[7]: Код V1.01
От: Andrew S Россия http://alchemy-lab.com
Дата: 12.08.04 10:30
Оценка:
AS>>А вот сроковым литералом, который имеет internal linkage и тип const TCHAR[] — нельзя.
__>Потому что это внешняя линковка, а все что внутреняя нельзя использовать.

Это все понятно.

__>Зато можно сделать такое :


В VC6 — нельзя. Можно только без спецификатора const.
__>
__>template<const TCHAR s>
__>struct x{};

__>#define DEF_STR(strname,str) \
__> const TCHAR strname##__unique_name[] = str; \
__> x<strname##__unique_name> some_type##str_name;
__>


__>>>Мне кажется лучше вместо DWORD делать так :

__>>>
__>>>template<
__>>>        TCHAR c0=0,
__>>>        TCHAR c1=0,
__>>>        TCHAR c2=0,
__>>>        TCHAR c3=0,
__>>>                //...
    >>>>
__>>>class CNameIdHolderImpl
__>>>{
__>>>};
__>>>


__>>>И не будет проблем с разложением DWORD.



Будут проблемы другого плана — в каждом модуле линковки будет своя таблица (поскольку специализации, в данном случае адреса массивов), будут различаться. А нам то нужно как раз обратно — обеспечить кросс-модульность.

__>Или может лучше сделать через Traits ?


__>
__>template<typename TTraits>
__>class x;

__>struct traits_kernel32_lib
__>{ static LPCTSTR get_name() { return "kernel32.lib" } };

__>x<traits_kernel32_lib> lib_kernel;
__>

__>Или оформить в виде макроса.
__>Тогда нет проблем со строкой и нет проблем с разбором строки и нет проблем с глобальной переменной.

__>
__>#define USE_MODULE_BEGIN(nmspace, id, NameId) \
__>namespace nmspace \
__>{\
__>    struct nmspace##_traits##id##__unique_name
__>    { static LPCTSTR get_name() { return NameId; } };
__>    typedef CModule< CNameId< nmspace##_traits##id##__unique_name > > module_type;\
__>


__>Ну или что-то вроде того


Аналогичная проблема, только, за исключением того, что придется делать трейты для всех функций, библиотеку и т.п. что используются в программе, выносить их в отдельный заголовочный файл, а это убивает изначальную гибкость конструкции.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[8]: Код V1.01
От: _nn_ www.nemerleweb.com
Дата: 12.08.04 12:29
Оценка:
Здравствуйте, Andrew S, Вы писали:

Проблемы одни

А теперь сначала все

Что делает CNameIdHolder ?
Создает строку из нескольких двойных слов, вместо этого можно использовать обычные символы, и тогда не нужен будет макрос FLATTEN_STR, зато писать надо немного утомительно :
typedef CModule<
  CNameId<'k','e','r','n','e','l','3','2','.','d','l','l'>
 >kernel_module_type;

Зато макрос не нужен

И выйдет что-то такое :
template<TCHAR c0=0,
         TCHAR c1=0,
         TCHAR c2=0,
         TCHAR c3=0,
         //...
        >
struct CNameId
{
  enum
  {
        m_c0 = c0,
        m_c1 = c1,
        m_c2 = c2,
        //...
        count   = (!c0) ? 0: 
                  (!c1) ? 1: 
                  (!c2) ? 2:
                  //...
   };
   static LPCTSTR GetStr()
   {
       static TCHAR strName[] =
       {
         c0,
         c1,
         c2,
         //...
         0
       };
       return strName;  
  }
};


Нет лишних классов, лишнего кода, лишних специализаций
И все красиво и понятно
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[9]: Код V1.01
От: Andrew S Россия http://alchemy-lab.com
Дата: 12.08.04 13:27
Оценка:
__>Проблемы одни

А в С++ так всегда — когда кажется, что проблем нет, то это только кажется.

__>А теперь сначала все


__>Что делает CNameIdHolder ?

__>Создает строку из нескольких двойных слов, вместо этого можно использовать обычные символы, и тогда не нужен будет макрос FLATTEN_STR, зато писать надо немного утомительно :

Нет, он статически инициализирует массив _подходящей_ длины. В вашем случае вам придется делать 32 специализации, иначе получите большой оверхед по длине массива. да и запись каждого символа по-отдельности это совсем некрасиво.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[10]: Код V1.01
От: _nn_ www.nemerleweb.com
Дата: 12.08.04 14:20
Оценка:
Здравствуйте, Andrew S, Вы писали:

__>>Проблемы одни


AS>А в С++ так всегда — когда кажется, что проблем нет, то это только кажется.


__>>А теперь сначала все


__>>Что делает CNameIdHolder ?

__>>Создает строку из нескольких двойных слов, вместо этого можно использовать обычные символы, и тогда не нужен будет макрос FLATTEN_STR, зато писать надо немного утомительно :

AS>Нет, он статически инициализирует массив _подходящей_ длины. В вашем случае вам придется делать 32 специализации, иначе получите большой оверхед по длине массива.

Оверхед, да будет, но не настолько большой.
Допустип ограничимся 32 символами, на 100 классов будет максимальный оверхед в 32*100 = 3,2кБ, я не думаю что для программы, размер которой несколько сот кБ это критично.
AS>да и запись каждого символа по-отдельности это совсем некрасиво.
А в оригинале разве не так ?

В крайнем случае сделаем макросы аналоги в boost-е и воспользуемся ими
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[11]: Код V1.01
От: Andrew S Россия http://alchemy-lab.com
Дата: 12.08.04 14:28
Оценка:
__>Допустип ограничимся 32 символами, на 100 классов будет максимальный оверхед в 32*100 = 3,2кБ, я не думаю что для программы, размер которой несколько сот кБ это критично.

Может и не критично, но тогда в чем смысл всей этой городни с синглтонами и т.п. Если есть возможность делать оптимальнее при разработке библиотеки — это надо сделать.

AS>>да и запись каждого символа по-отдельности это совсем некрасиво.

__>А в оригинале разве не так ?

Нет, не так Некрасиво — да, но все-таки не по-одному, а пачками по четыре Хотя, конечно, уродство все это

__>В крайнем случае сделаем макросы аналоги в boost-е и воспользуемся ими


Ну, ждем предложений Вам и карты в руки.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[12]: Код V1.01
От: _nn_ www.nemerleweb.com
Дата: 12.08.04 14:30
Оценка:
Здравствуйте, Andrew S, Вы писали:

AS>Ну, ждем предложений Вам и карты в руки.


Сейчас попробую
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[2]: CNameID v1.02
От: _nn_ www.nemerleweb.com
Дата: 12.08.04 15:34
Оценка: 1 (1)
Здравствуйте, Andrew S, Вы писали:

Как вам такой вариант :
// CAT
#define CAT_(x,y) x##y
#define CAT(x,y) CAT_(x,y)

// REPEAT_N
#define REPEAT_N_0(x) CAT(x,0)
#define REPEAT_N_1(x) REPEAT_N_0(x), CAT(x,1)
#define REPEAT_N_2(x) REPEAT_N_1(x), CAT(x,2)
#define REPEAT_N_3(x) REPEAT_N_2(x), CAT(x,3)
//...
#define REPEAT_N(n,x) CAT(REPEAT_N_,n)(x)

// REPEAT_EX_N
#define REPEAT_EX_N_0(x,y) CAT(CAT(x,0),y)
#define REPEAT_EX_N_1(x,y) REPEAT_EX_N_0(x,y), CAT(CAT(x,1),y)
#define REPEAT_EX_N_2(x,y) REPEAT_EX_N_1(x,y), CAT(CAT(x,2),y)
#define REPEAT_EX_N_3(x,y) REPEAT_EX_N_2(x,y), CAT(CAT(x,3),y)
//...
#define REPEAT_EX_N(n,x,y) CAT(REPEAT_EX_N_,n)(x,y)

// REPEAT_EX2_N
#define REPEAT_EX2_N_0(x,y) CAT(CAT(x,0),CAT(y,0))
#define REPEAT_EX2_N_1(x,y) REPEAT_EX2_N_0(x,y), CAT(CAT(x,1),CAT(y,1))
#define REPEAT_EX2_N_2(x,y) REPEAT_EX2_N_1(x,y), CAT(CAT(x,2),CAT(y,2))
#define REPEAT_EX2_N_3(x,y) REPEAT_EX2_N_2(x,y), CAT(CAT(x,3),CAT(y,3))
//...
#define REPEAT_EX2_N(n,x,y) CAT(REPEAT_EX2_N_,n)(x,y)

// DECLARE_CNAMEID
#define CNAME_ID_(n) \
{ \
    enum \
    { \
        REPEAT_EX2_N(n,m_c,t_c) \
    }; \
    static const TCHAR* GetStr() \
    { \
        static const TCHAR str[]= \
        { \
            REPEAT_N(n,t_c) \
            ,0 \
        }; \
        return str; \
    } \
};

#define SPEC_CNAMEID(n) \
template<REPEAT_N(n,TCHAR t_c)> \
struct CNameID<REPEAT_N(n,t_c)> \
CNAME_ID_(n)

#define DECLARE_CNAMEID(n) \
template<REPEAT_EX_N(n,TCHAR t_c,=0)> \
struct CNameID \
CNAME_ID_(n)

// определяем сам класс
DECLARE_CNAMEID(2)
// специализации
SPEC_CNAMEID(0)
SPEC_CNAMEID(1)

// тестим
void main()
{
 const TCHAR* str = CNameID<'a','b','c'>::GetStr();
}
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[3]: CNameID v1.02
От: Andrew S Россия http://alchemy-lab.com
Дата: 12.08.04 18:18
Оценка:
__>Как вам такой вариант :

[skipped]

Мне — почти никак, он на VC6 компилится не будет, как я понял — там у вас частичная специализация?
В любом случае, это почти ничего не меняет, ну, кроме конечно размеров исходников, тем более, как я говорил, мне мысль использовать односимвольные числовые литералы почему то не нравится, хотя начиналось все именно так.

На самом деле, наверное, лучше подумать над более глобальной проблемой — как удобнее сделать макросы
USE_MODULE_BEGIN и DECLARE_FUN_P1 в части задания имени. То, что есть сейчас, явно неудобно...
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[4]: CNameID v1.02
От: _nn_ www.nemerleweb.com
Дата: 13.08.04 06:50
Оценка:
Здравствуйте, Andrew S, Вы писали:

__>>Как вам такой вариант :


AS>[skipped]


AS>Мне — почти никак, он на VC6 компилится не будет, как я понял — там у вас частичная специализация?

Забыл про VC6
А чем вам оверхед мешает ?
Зато все строки будут одинаковой длинны
AS>В любом случае, это почти ничего не меняет, ну, кроме конечно размеров исходников, тем более, как я говорил, мне мысль использовать односимвольные числовые литералы почему то не нравится, хотя начиналось все именно так.
Односимвольные литералы лучше, так как позволяют избежать проблемы вроде этой :
CModule<'some','tex','t'>


Мне кажется что стоит сделать какой-нибудь класс для преобразования строки в односимвольные литералы, и тогда проблем не будет.

template<TCHAR c0,TCHAR c1, ... >
struct CNameID
{...};

template<typename T,TCHAR str[]>
class str_to_char
{
 typedef T<str[0],str[1],...> type;  // как правильно не знаю :xz: 
};

Надеюсь идея ясна.

AS>На самом деле, наверное, лучше подумать над более глобальной проблемой — как удобнее сделать макросы

AS>USE_MODULE_BEGIN и DECLARE_FUN_P1 в части задания имени. То, что есть сейчас, явно неудобно...
Если решить проблемы выше то это отпадет само собой.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[5]: CNameID v1.02
От: Andrew S Россия http://alchemy-lab.com
Дата: 13.08.04 07:24
Оценка:
__>Мне кажется что стоит сделать какой-нибудь класс для преобразования строки в односимвольные литералы, и тогда проблем не будет.

__>
__>template<TCHAR c0,TCHAR c1, ... >
__>struct CNameID
__>{...};

__>template<typename T,TCHAR str[]>
__>class str_to_char
__>{
__> typedef T<str[0],str[1],...> type;  // как правильно не знаю :xz: 
__>};
__>

__>Надеюсь идея ясна.

Ну, и подумайте, что вы предлагаете Хинт — при инстанцировании класса CNameID параметрами должны быть символьные литералы (то бишь константы).

AS>>На самом деле, наверное, лучше подумать над более глобальной проблемой — как удобнее сделать макросы

AS>>USE_MODULE_BEGIN и DECLARE_FUN_P1 в части задания имени. То, что есть сейчас, явно неудобно...
__>Если решить проблемы выше то это отпадет само собой.

Да, если решить проблемы Я (и не только я) пробовал, не получилось. Точнее, получилось то, что получилось.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[6]: CNameID v1.02
От: _nn_ www.nemerleweb.com
Дата: 13.08.04 07:47
Оценка:
Здравствуйте, Andrew S, Вы писали:

__>>Мне кажется что стоит сделать какой-нибудь класс для преобразования строки в односимвольные литералы, и тогда проблем не будет.


__>>
__>>template<TCHAR c0,TCHAR c1, ... >
__>>struct CNameID
__>>{...};

__>>template<typename T,TCHAR str[]>
__>>class str_to_char
__>>{
__>> typedef T<str[0],str[1],...> type;  // как правильно не знаю :xz: 
__>>};
__>>

__>>Надеюсь идея ясна.

AS>Ну, и подумайте, что вы предлагаете Хинт — при инстанцировании класса CNameID параметрами должны быть символьные литералы (то бишь константы).

Инстанирование будет литералами, а извне это будет в виде массива.

AS>>>На самом деле, наверное, лучше подумать над более глобальной проблемой — как удобнее сделать макросы

AS>>>USE_MODULE_BEGIN и DECLARE_FUN_P1 в части задания имени. То, что есть сейчас, явно неудобно...
__>>Если решить проблемы выше то это отпадет само собой.

AS>Да, если решить проблемы Я (и не только я) пробовал, не получилось. Точнее, получилось то, что получилось.

Как только доберусь нормально до компьютера попробую что-нибудь сотворить
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[7]: CNameID v1.02
От: Andrew S Россия http://alchemy-lab.com
Дата: 13.08.04 12:50
Оценка:
AS>>Ну, и подумайте, что вы предлагаете Хинт — при инстанцировании класса CNameID параметрами должны быть символьные литералы (то бишь константы).
__>Инстанирование будет литералами, а извне это будет в виде массива.

Не получится. Надо инстанцировать константами, а вы предлагаете инстанцировать фактически содержимым ячеек памяти, что на этапе компиляции компилеру не известно (ведь темплайт в данном случае инстанцируется адресом, к сожалению, а не содержимым).

AS>>>>На самом деле, наверное, лучше подумать над более глобальной проблемой — как удобнее сделать макросы

AS>>>>USE_MODULE_BEGIN и DECLARE_FUN_P1 в части задания имени. То, что есть сейчас, явно неудобно...
__>>>Если решить проблемы выше то это отпадет само собой.

AS>>Да, если решить проблемы Я (и не только я) пробовал, не получилось. Точнее, получилось то, что получилось.

__>Как только доберусь нормально до компьютера попробую что-нибудь сотворить
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[8]: CNameID v1.02
От: _nn_ www.nemerleweb.com
Дата: 13.08.04 18:51
Оценка: 14 (1)
Здравствуйте, Andrew S, Вы писали:

AS>>>Ну, и подумайте, что вы предлагаете Хинт — при инстанцировании класса CNameID параметрами должны быть символьные литералы (то бишь константы).

__>>Инстанирование будет литералами, а извне это будет в виде массива.

AS>Не получится. Надо инстанцировать константами, а вы предлагаете инстанцировать фактически содержимым ячеек памяти, что на этапе компиляции компилеру не известно (ведь темплайт в данном случае инстанцируется адресом, к сожалению, а не содержимым).

Вы меня не так поняли
Ну ладно это не важно, я попробую переработать это для совместимости с VC 6 и выложу на форум.
Главное ведь результат

AS>>>>>На самом деле, наверное, лучше подумать над более глобальной проблемой — как удобнее сделать макросы

AS>>>>>USE_MODULE_BEGIN и DECLARE_FUN_P1 в части задания имени. То, что есть сейчас, явно неудобно...
__>>>>Если решить проблемы выше то это отпадет само собой.

AS>>>Да, если решить проблемы Я (и не только я) пробовал, не получилось. Точнее, получилось то, что получилось.

__>>Как только доберусь нормально до компьютера попробую что-нибудь сотворить
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[2]: CNameID 1.03
От: _nn_ www.nemerleweb.com
Дата: 14.08.04 10:20
Оценка:
Переработал с целью совместимости с VC 6.0.

// CAT
#define CAT_(x,y) x##y
#define CAT(x,y) CAT_(x,y)

// REPEAT_N
#define REPEAT_N_0(x) CAT(x,0)
#define REPEAT_N_1(x) REPEAT_N_0(x), CAT(x,1)
#define REPEAT_N_2(x) REPEAT_N_1(x), CAT(x,2)
#define REPEAT_N_3(x) REPEAT_N_2(x), CAT(x,3)
#define REPEAT_N_4(x) REPEAT_N_3(x), CAT(x,4)
#define REPEAT_N_5(x) REPEAT_N_4(x), CAT(x,5)
#define REPEAT_N_6(x) REPEAT_N_5(x), CAT(x,6)
#define REPEAT_N_7(x) REPEAT_N_6(x), CAT(x,7)
#define REPEAT_N_8(x) REPEAT_N_7(x), CAT(x,8)
//...
#define REPEAT_N(n,x) CAT(REPEAT_N_,n)(x)

// REPEAT2_N
#define REPEAT2_N_0(x,y) CAT(CAT(x,0),y)
#define REPEAT2_N_1(x,y) REPEAT2_N_0(x,y), CAT(CAT(x,1),y)
#define REPEAT2_N_2(x,y) REPEAT2_N_1(x,y), CAT(CAT(x,2),y)
#define REPEAT2_N_3(x,y) REPEAT2_N_2(x,y), CAT(CAT(x,3),y)
#define REPEAT2_N_4(x,y) REPEAT2_N_3(x,y), CAT(CAT(x,4),y)
#define REPEAT2_N_5(x,y) REPEAT2_N_4(x,y), CAT(CAT(x,5),y)
#define REPEAT2_N_6(x,y) REPEAT2_N_5(x,y), CAT(CAT(x,6),y)
#define REPEAT2_N_7(x,y) REPEAT2_N_6(x,y), CAT(CAT(x,7),y)
#define REPEAT2_N_8(x,y) REPEAT2_N_7(x,y), CAT(CAT(x,8),y)
//...
#define REPEAT2_N(n,x,y) CAT(REPEAT2_N_,n)(x,y)

// REPEAT2_EX_N
#define REPEAT2_EX_N_0(x,y) CAT(CAT(x,0),CAT(y,0))
#define REPEAT2_EX_N_1(x,y) REPEAT2_EX_N_0(x,y), CAT(CAT(x,1),CAT(y,1))
#define REPEAT2_EX_N_2(x,y) REPEAT2_EX_N_1(x,y), CAT(CAT(x,2),CAT(y,2))
#define REPEAT2_EX_N_3(x,y) REPEAT2_EX_N_2(x,y), CAT(CAT(x,3),CAT(y,3))
#define REPEAT2_EX_N_4(x,y) REPEAT2_EX_N_3(x,y), CAT(CAT(x,4),CAT(y,4))
#define REPEAT2_EX_N_5(x,y) REPEAT2_EX_N_4(x,y), CAT(CAT(x,5),CAT(y,5))
#define REPEAT2_EX_N_6(x,y) REPEAT2_EX_N_5(x,y), CAT(CAT(x,6),CAT(y,6))
#define REPEAT2_EX_N_7(x,y) REPEAT2_EX_N_6(x,y), CAT(CAT(x,7),CAT(y,7))
#define REPEAT2_EX_N_8(x,y) REPEAT2_EX_N_7(x,y), CAT(CAT(x,8),CAT(y,8))
//...
#define REPEAT2_EX_N(n,x,y) CAT(REPEAT2_EX_N_,n)(x,y)

// REPEAT3_NC_N
#define REPEAT3_NC_N_0(x,y,z) CAT(CAT(CAT(x,0),CAT(y,0)),z)
#define REPEAT3_NC_N_1(x,y,z) REPEAT3_NC_N_0(x,y,z) CAT(CAT(CAT(x,1),CAT(y,1)),z)
#define REPEAT3_NC_N_2(x,y,z) REPEAT3_NC_N_1(x,y,z) CAT(CAT(CAT(x,2),CAT(y,2)),z)
#define REPEAT3_NC_N_3(x,y,z) REPEAT3_NC_N_2(x,y,z) CAT(CAT(CAT(x,3),CAT(y,3)),z)
#define REPEAT3_NC_N_4(x,y,z) REPEAT3_NC_N_3(x,y,z) CAT(CAT(CAT(x,4),CAT(y,4)),z)
#define REPEAT3_NC_N_5(x,y,z) REPEAT3_NC_N_4(x,y,z) CAT(CAT(CAT(x,5),CAT(y,5)),z)
#define REPEAT3_NC_N_6(x,y,z) REPEAT3_NC_N_5(x,y,z) CAT(CAT(CAT(x,6),CAT(y,6)),z)
#define REPEAT3_NC_N_7(x,y,z) REPEAT3_NC_N_6(x,y,z) CAT(CAT(CAT(x,7),CAT(y,7)),z)
#define REPEAT3_NC_N_8(x,y,z) REPEAT3_NC_N_7(x,y,z) CAT(CAT(CAT(x,8),CAT(y,8)),z)
//...
#define REPEAT3_NC_N(n,x,y,z) CAT(REPEAT3_NC_N_,n)(x,y,z)

// CNameID
#define DECLARE_CNAMEID_IMPL(n) \
    template<unsigned N> \
    struct CNameIDImpl \
    CNAMEID_IMPL_(n,n)

#define SPEC_CNAMEID_IMPL(N,n) \
    template<> \
    struct CNameIDImpl<n> \
    CNAMEID_IMPL_(N,n)

#define CNAMEID_IMPL_(N,n) \
    { \
        template<REPEAT2_EX_N(N,TCHAR t_c,=0)> \
        struct Impl \
        { \
            static const TCHAR* GetStr() \
            { \
                static const TCHAR str[]= \
                { \
                    REPEAT_N(n,t_c), \
                    0 \
                }; \
                return str; \
            } \
        }; \
    };

#define DECLARE_CNAMEID(n) \
    template<REPEAT2_N(n,TCHAR t_c,=0)> \
    struct CNameID \
    { \
        enum \
        { \
            REPEAT2_EX_N(n,m_c,t_c), \
            count = REPEAT3_NC_N(n,!t_c,?,:) n+1 \
        }; \
        static const TCHAR* GetStr() \
        { return CNameIDImpl<count>::Impl<REPEAT_N(n,t_c)>::GetStr(); } \
    };

DECLARE_CNAMEID_IMPL(7)
SPEC_CNAMEID_IMPL(7,0)
SPEC_CNAMEID_IMPL(7,1)
SPEC_CNAMEID_IMPL(7,2)
SPEC_CNAMEID_IMPL(7,3)
SPEC_CNAMEID_IMPL(7,4)
SPEC_CNAMEID_IMPL(7,5)
SPEC_CNAMEID_IMPL(7,6)

DECLARE_CNAMEID(7)


Тестим
void main()
{
    int n0 = CNameID<>::count;
    const TCHAR* s0 = CNameID<>::GetStr();
    int n1 = CNameID<'a'>::count;
    const TCHAR* s1 = CNameID<'a'>::GetStr();
    int n2 = CNameID<'a','b'>::count;
    const TCHAR* s2 = CNameID<'a','b'>::GetStr();
    int n3 = CNameID<'a','b','c'>::count;
    const TCHAR* s3 = CNameID<'a','b','c'>::GetStr();
    int n4 = CNameID<'a','b','c','d'>::count;
    const TCHAR* s4 = CNameID<'a','b','c','d'>::GetStr();
    int n5 = CNameID<'a','b','c','d','e'>::count;
    const TCHAR* s5 = CNameID<'a','b','c','d','e'>::GetStr();
}
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re: Pure C++ delay load
От: Andrew S Россия http://alchemy-lab.com
Дата: 16.08.04 15:29
Оценка:
Большое спасибо _nn_ за проявленную инициативу, в связи с чем выкладываю обновление до v 1.03
Специализация выполнена на макросах, максимальная длина строки увеличена до 64 символов, можно без особых изменений в коде и больше.
На макросы определения функций терпения не хватило, а common вариант не придумался — если есть мысли, будет интересно выслушать.
И, как обычно — если есть какие предложения (ну, кроме использования буста, тут это как из пушки по воробьям) — u are welcome.

//    delayimphlp.h: Delay import helper
//    Developer:    Andrew Solodovnikov
//    E-mail:        none
//    Date:        03.08.2004

#ifndef    __DELAYIMPHLP_H__
#define __DELAYIMPHLP_H__

#define DL_CAT_(x,y) x##y
#define DL_CAT(x,y) DL_CAT_(x,y)

#define MAX_DL_REPEAT 16

#define DL_REPEAT_EMPTY_PARAM()

// DL_REPEAT_N
#define DL_REPEAT_N_0(x) 
#define DL_REPEAT_N_1(x) DL_CAT(x,1)
#define DL_REPEAT_N_2(x) DL_REPEAT_N_1(x), DL_CAT(x,2)
#define DL_REPEAT_N_3(x) DL_REPEAT_N_2(x), DL_CAT(x,3)
#define DL_REPEAT_N_4(x) DL_REPEAT_N_3(x), DL_CAT(x,4)
#define DL_REPEAT_N_5(x) DL_REPEAT_N_4(x), DL_CAT(x,5)
#define DL_REPEAT_N_6(x) DL_REPEAT_N_5(x), DL_CAT(x,6)
#define DL_REPEAT_N_7(x) DL_REPEAT_N_6(x), DL_CAT(x,7)
#define DL_REPEAT_N_8(x) DL_REPEAT_N_7(x), DL_CAT(x,8)
#define DL_REPEAT_N_9(x) DL_REPEAT_N_8(x), DL_CAT(x,9)
#define DL_REPEAT_N_10(x) DL_REPEAT_N_9(x), DL_CAT(x,10)
#define DL_REPEAT_N_11(x) DL_REPEAT_N_10(x), DL_CAT(x,11)
#define DL_REPEAT_N_12(x) DL_REPEAT_N_11(x), DL_CAT(x,12)
#define DL_REPEAT_N_13(x) DL_REPEAT_N_12(x), DL_CAT(x,13)
#define DL_REPEAT_N_14(x) DL_REPEAT_N_13(x), DL_CAT(x,14)
#define DL_REPEAT_N_15(x) DL_REPEAT_N_14(x), DL_CAT(x,15)
#define DL_REPEAT_N_16(x) DL_REPEAT_N_15(x), DL_CAT(x,16)

#define DL_REPEAT_N(n, x) DL_CAT(DL_REPEAT_N_,n)(x)



// DL_REPEAT_PARAM_N
#define DL_REPEAT_PARAM_N0(n, m)
#define DL_REPEAT_PARAM_N1(n, m) DL_CAT(n,1) DL_CAT(m,1)
#define DL_REPEAT_PARAM_N2(n, m) DL_REPEAT_PARAM_N1(n, m), DL_CAT(n,2) DL_CAT(m,2)
#define DL_REPEAT_PARAM_N3(n, m) DL_REPEAT_PARAM_N2(n, m), DL_CAT(n,3) DL_CAT(m,3)
#define DL_REPEAT_PARAM_N4(n, m) DL_REPEAT_PARAM_N3(n, m), DL_CAT(n,4) DL_CAT(m,4)
#define DL_REPEAT_PARAM_N5(n, m) DL_REPEAT_PARAM_N4(n, m), DL_CAT(n,5) DL_CAT(m,5)
#define DL_REPEAT_PARAM_N6(n, m) DL_REPEAT_PARAM_N5(n, m), DL_CAT(n,6) DL_CAT(m,6)
#define DL_REPEAT_PARAM_N7(n, m) DL_REPEAT_PARAM_N6(n, m), DL_CAT(n,7) DL_CAT(m,7)
#define DL_REPEAT_PARAM_N8(n, m) DL_REPEAT_PARAM_N7(n, m), DL_CAT(n,8) DL_CAT(m,8)
#define DL_REPEAT_PARAM_N9(n, m) DL_REPEAT_PARAM_N8(n, m), DL_CAT(n,9) DL_CAT(m,9)
#define DL_REPEAT_PARAM_N10(n, m) DL_REPEAT_PARAM_N9(n, m), DL_CAT(n,10) DL_CAT(m,10)
#define DL_REPEAT_PARAM_N11(n, m) DL_REPEAT_PARAM_N10(n, m), DL_CAT(n,11) DL_CAT(m,11)
#define DL_REPEAT_PARAM_N12(n, m) DL_REPEAT_PARAM_N11(n, m), DL_CAT(n,12) DL_CAT(m,12)
#define DL_REPEAT_PARAM_N13(n, m) DL_REPEAT_PARAM_N12(n, m), DL_CAT(n,13) DL_CAT(m,13)
#define DL_REPEAT_PARAM_N14(n, m) DL_REPEAT_PARAM_N13(n, m), DL_CAT(n,14) DL_CAT(m,14)
#define DL_REPEAT_PARAM_N15(n, m) DL_REPEAT_PARAM_N14(n, m), DL_CAT(n,15) DL_CAT(m,15)
#define DL_REPEAT_PARAM_N16(n,m) DL_REPEAT_PARAM_N15(n, m), DL_CAT(n,16) DL_CAT(m,16)

#define DL_REPEAT_PARAM_N(c, n, m) DL_CAT(DL_REPEAT_PARAM_N,c)(n, m)

// DL_REPEAT_DEF_N
#define DL_REPEAT_DEF_N0(n, d)
#define DL_REPEAT_DEF_N1(n, d) DL_CAT(DL_CAT(n,1), d)
#define DL_REPEAT_DEF_N2(n, d) DL_REPEAT_DEF_N1(n, d), DL_CAT(DL_CAT(n,2), d)
#define DL_REPEAT_DEF_N3(n, d) DL_REPEAT_DEF_N2(n, d), DL_CAT(DL_CAT(n,3), d)
#define DL_REPEAT_DEF_N4(n, d) DL_REPEAT_DEF_N3(n, d), DL_CAT(DL_CAT(n,4), d)
#define DL_REPEAT_DEF_N5(n, d) DL_REPEAT_DEF_N4(n, d), DL_CAT(DL_CAT(n,5), d)
#define DL_REPEAT_DEF_N6(n, d) DL_REPEAT_DEF_N5(n, d), DL_CAT(DL_CAT(n,6), d)
#define DL_REPEAT_DEF_N7(n, d) DL_REPEAT_DEF_N6(n, d), DL_CAT(DL_CAT(n,7), d)
#define DL_REPEAT_DEF_N8(n, d) DL_REPEAT_DEF_N7(n, d), DL_CAT(DL_CAT(n,8), d)
#define DL_REPEAT_DEF_N9(n, d) DL_REPEAT_DEF_N8(n, d), DL_CAT(DL_CAT(n,9), d)
#define DL_REPEAT_DEF_N10(n, d) DL_REPEAT_DEF_N9(n, d), DL_CAT(DL_CAT(n,10), d)
#define DL_REPEAT_DEF_N11(n, d) DL_REPEAT_DEF_N10(n, d), DL_CAT(DL_CAT(n,11), d)
#define DL_REPEAT_DEF_N12(n, d) DL_REPEAT_DEF_N11(n, d), DL_CAT(DL_CAT(n,12), d)
#define DL_REPEAT_DEF_N13(n, d) DL_REPEAT_DEF_N12(n, d), DL_CAT(DL_CAT(n,13), d)
#define DL_REPEAT_DEF_N14(n, d) DL_REPEAT_DEF_N13(n, d), DL_CAT(DL_CAT(n,14), d)
#define DL_REPEAT_DEF_N15(n, d) DL_REPEAT_DEF_N14(n, d), DL_CAT(DL_CAT(n,15), d)
#define DL_REPEAT_DEF_N16(n,d) DL_REPEAT_DEF_N15(n, d), DL_CAT(DL_CAT(n,16), d)

#define DL_REPEAT_DEF_N(c, n, d) DL_CAT(DL_REPEAT_DEF_N,c)(n, d)


// DL_REPEAT_MACRO_N

#define DL_REPEAT_MACRO_N0(m, p)
#define DL_REPEAT_MACRO_N1(m, p) m(DL_CAT(p,1))
#define DL_REPEAT_MACRO_N2(m, p) DL_REPEAT_MACRO_N1(m, p), m(DL_CAT(p,2))
#define DL_REPEAT_MACRO_N3(m, p) DL_REPEAT_MACRO_N2(m, p), m(DL_CAT(p,3))
#define DL_REPEAT_MACRO_N4(m, p) DL_REPEAT_MACRO_N3(m, p), m(DL_CAT(p,4))
#define DL_REPEAT_MACRO_N5(m, p) DL_REPEAT_MACRO_N4(m, p), m(DL_CAT(p,5))
#define DL_REPEAT_MACRO_N6(m, p) DL_REPEAT_MACRO_N5(m, p), m(DL_CAT(p,6))
#define DL_REPEAT_MACRO_N7(m, p) DL_REPEAT_MACRO_N6(m, p), m(DL_CAT(p,7))
#define DL_REPEAT_MACRO_N8(m, p) DL_REPEAT_MACRO_N7(m, p), m(DL_CAT(p,8))
#define DL_REPEAT_MACRO_N9(m, p) DL_REPEAT_MACRO_N8(m, p), m(DL_CAT(p,9))
#define DL_REPEAT_MACRO_N10(m, p) DL_REPEAT_MACRO_N9(m, p), m(DL_CAT(p,10))
#define DL_REPEAT_MACRO_N11(m, p) DL_REPEAT_MACRO_N10(m, p), m(DL_CAT(p,11))
#define DL_REPEAT_MACRO_N12(m, p) DL_REPEAT_MACRO_N11(m, p), m(DL_CAT(p,12))
#define DL_REPEAT_MACRO_N13(m, p) DL_REPEAT_MACRO_N12(m, p), m(DL_CAT(p,13))
#define DL_REPEAT_MACRO_N14(m, p) DL_REPEAT_MACRO_N13(m, p), m(DL_CAT(p,14))
#define DL_REPEAT_MACRO_N15(m, p) DL_REPEAT_MACRO_N14(m, p), m(DL_CAT(p,15))
#define DL_REPEAT_MACRO_N16(m, p) DL_REPEAT_MACRO_N15(m, p), m(DL_CAT(p,16))

#define DL_REPEAT_MACRO_N(c, m, p) DL_CAT(DL_REPEAT_MACRO_N,c)(m,p)

#define FLATTEN_STR(val) \
        (TCHAR)HIBYTE(HIWORD(val)), (TCHAR)LOBYTE(HIWORD(val)), (TCHAR)HIBYTE(LOWORD(val)), (TCHAR)LOBYTE(LOWORD(val))


#define    DECLARE_STR_DWORD(Name, Idx) \
static const TCHAR Name[] = {FLATTEN_STR(Idx##0), FLATTEN_STR(Idx##1), FLATTEN_STR(Idx##2), FLATTEN_STR(Idx##3), FLATTEN_STR(Idx##4), FLATTEN_STR(Idx##5), FLATTEN_STR(Idx##6), FLATTEN_STR(Idx##7)};


template <int count>
struct CNameIdHolder
{
    template <DL_REPEAT_N(MAX_DL_REPEAT, DWORD n)>
    struct CNameIdHolderImpl
    {
        static LPCTSTR GetStr()
        {
            static const TCHAR szBuffer[] = {
                                                DL_REPEAT_MACRO_N(MAX_DL_REPEAT, FLATTEN_STR, n),
                                                _T('\0')
                                            };
            return szBuffer;
        }
    };
};

#define NAME_ID_HOLDER_SPEC(num)\
template <>\
struct CNameIdHolder<num>\
{\
    template <DL_REPEAT_N(MAX_DL_REPEAT, DWORD n)>\
    struct CNameIdHolderImpl\
    {\
        static LPCTSTR GetStr()\
        {\
            static const TCHAR szBuffer[] = {\
                                                DL_REPEAT_MACRO_N(num, FLATTEN_STR, n),\
                                                _T('\0')\
                                            };\
            return szBuffer;\
        }\
    };\
};

NAME_ID_HOLDER_SPEC(15)
NAME_ID_HOLDER_SPEC(14)
NAME_ID_HOLDER_SPEC(13)
NAME_ID_HOLDER_SPEC(12)
NAME_ID_HOLDER_SPEC(11)
NAME_ID_HOLDER_SPEC(10)
NAME_ID_HOLDER_SPEC(9)
NAME_ID_HOLDER_SPEC(8)
NAME_ID_HOLDER_SPEC(7)
NAME_ID_HOLDER_SPEC(6)
NAME_ID_HOLDER_SPEC(5)
NAME_ID_HOLDER_SPEC(4)
NAME_ID_HOLDER_SPEC(3)
NAME_ID_HOLDER_SPEC(2)
NAME_ID_HOLDER_SPEC(1)

template <>
struct CNameIdHolder<0>
{
    template <DL_REPEAT_N(MAX_DL_REPEAT, DWORD n)>
    struct CNameIdHolderImpl
    {
        static LPCTSTR GetStr()
        {
            return NULL;
        }
    };
};


template <DL_REPEAT_DEF_N(MAX_DL_REPEAT, DWORD n, = 0)>
struct CNameId
{
    enum
    {
        DL_REPEAT_PARAM_N(MAX_DL_REPEAT, m_n, =n),
        count   = (!n1) ? 0: (!n2) ? 1: (!n3) ?2: (!n4) ? 3: (!n5) ? 4: (!n6) ? 5: (!n7) ? 6: (!n8) ? 7: 
                  (!n9) ? 8: (!n10) ? 9: (!n11) ?10: (!n12) ? 11: (!n13) ? 12: (!n14) ? 13: (!n15) ? 14: (!n16) ? 15: 16
    };
    static LPCTSTR GetStr()
    {
        return CNameIdHolder<count>::CNameIdHolderImpl<DL_REPEAT_N(MAX_DL_REPEAT, n)>::GetStr();
    }
};

template <class Name>
class CModule
{
public:
    HMODULE m_hModule;
    typedef CModule<Name> type;
    typedef Name          name_type;
    static type &GetModule()
    {
        static type Module;
        return Module;
    }
    ~CModule()
    {
        if (m_hModule)
            FreeLibrary(m_hModule);
    }
private:
    CModule()
    {
        m_hModule = LoadLibrary(name_type::GetStr());
    }
};


template <class Module, class Name, class Proxy>
class CDynFunction
{
public:
    typedef CDynFunction<Module, Name, Proxy> type;
    typedef Proxy                              proxy_type;
    typedef Module                              module_type;
    typedef Name                              name_type;
    
    static proxy_type::fun_type &GetProxy()
    {
        static proxy_type::fun_type proxy = proxy_type::Proxy<type>::ProxyFun;
        return proxy;
    }
    static BOOL InitFunction()
    {
        HMODULE hModule = Module::GetModule().m_hModule;
        if (hModule)
        {
            FARPROC pFunction = GetProcAddress(hModule, name_type::GetStr());
            if (pFunction)
            {
                GetProxy() = (proxy_type::fun_type)pFunction;
                return TRUE;
            }
        }
        return FALSE;
    }
};

template<class R, R value = R()>
struct FunProxyValuePolicy
{
    template <class DynFunction> 
    struct Dummy
    {
        static DynFunction::proxy_type::ret_type MakeReturn()
        {
            return value;
        }
    };
};

struct CDynFunException
{
    CDynFunException();
    CDynFunException(LPCTSTR sMessage):m_sMessage(sMessage)
    {
    }
    CDynFunException(const CDynFunException &other):m_sMessage(other.m_sMessage)
    {
    }
    CDynFunException &operator = (const CDynFunException &other)
    {
        m_sMessage = other.m_sMessage;
        return *this;
    }
    CString m_sMessage;
};

template<class E = CDynFunException>
struct FunProxyThrowPolicy
{
    template <class DynFunction> 
    struct Dummy
    {
        static DynFunction::proxy_type::ret_type MakeReturn()
        {
            CString sMessage;
            sMessage.Format(_T("Can'n load procedure <%s>: %d"), DynFunction::name_type::GetStr(), GetLastError());
            throw E(sMessage);
            return 0;
        }
    };
};



#define FUN_PROXY(n) DL_CAT(FunProxy,n)

#define DECLARE_FUN_PROXY(param_count) \
template <typename R, DL_REPEAT_N(param_count, typename P), class Policy = FunProxyValuePolicy<R> > struct FUN_PROXY(param_count)\
{\
    typedef R (WINAPI *fun_type)(DL_REPEAT_N(param_count, P));\
    typedef R ret_type;\
    template <class DynFunction> struct Proxy\
    {\
        static R WINAPI ProxyFun(DL_REPEAT_PARAM_N(param_count, P, v))\
        {\
            if (DynFunction::InitFunction())\
                return DynFunction::GetProxy()(DL_REPEAT_N(param_count, v));\
            return Policy::Dummy<DynFunction>::MakeReturn();\
        }\
    };\
};


DECLARE_FUN_PROXY(1)
DECLARE_FUN_PROXY(2)
DECLARE_FUN_PROXY(3)
DECLARE_FUN_PROXY(4)
DECLARE_FUN_PROXY(5)
DECLARE_FUN_PROXY(6)
DECLARE_FUN_PROXY(7)
DECLARE_FUN_PROXY(8)
DECLARE_FUN_PROXY(9)
DECLARE_FUN_PROXY(10)
DECLARE_FUN_PROXY(11)
DECLARE_FUN_PROXY(12)
DECLARE_FUN_PROXY(13)
DECLARE_FUN_PROXY(14)
DECLARE_FUN_PROXY(15)
DECLARE_FUN_PROXY(16)

// usefull macro's

#define USE_MODULE_BEGIN(nmspace, NameId) \
namespace nmspace \
{\
    typedef CModule< CNameId< /NameId/ > > module_type;

#define USE_MODULE_END \
};



#define DECLARE_FUN_P1(Name, NameId, R, P1) \
static R (WINAPI *&Name)(P1) = CDynFunction<module_type, CNameId< /NameId/ >, FUN_PROXY(1)<R, P1> >::GetProxy();


#define DECLARE_FUN_P1_ERR(Name, NameId, R, P1, E)\
static R (WINAPI *&Name)(P1) = CDynFunction<module_type, CNameId< /NameId/ >, FUN_PROXY(1)<R, P1, FunProxyValuePolicy<R, E> > >::GetProxy();
 
#define DECLARE_FUN_P1_THROW(Name, NameId, R, P1)\
static R (WINAPI *&Name)(P1) = CDynFunction<module_type, CNameId< /NameId/ >, FUN_PROXY(1)<R, P1, FunProxyThrowPolicy<> > >::GetProxy();

#endif
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[2]: Pure C++ delay load
От: _nn_ www.nemerleweb.com
Дата: 17.08.04 07:24
Оценка:
Здравствуйте, Andrew S, Вы писали:

AS>Большое спасибо _nn_ за проявленную инициативу, в связи с чем выкладываю обновление до v 1.03

AS>Специализация выполнена на макросах, максимальная длина строки увеличена до 64 символов, можно без особых изменений в коде и больше.
AS>На макросы определения функций терпения не хватило, а common вариант не придумался — если есть мысли, будет интересно выслушать.

Есть идея, но она мне кажется неосуществима.
Что-то такое :
#define CAT_0(x) CAT(x,0)
//...
#define CAT_n(x) CAT(x,n)

#define REPEAT_N(nfrom,nto,x) CAT(CAT_,nfrom)(x) /* как-нибудь перебор */ CAT(CAT_(nto))(x)


Вместо _T('\0') лучше писать просто 0, меньше проблем, вдобавок макрос _T определяется в commctrl.h, а если он не будет подключен то будут проблемы.

Есть еще предложение убрать CString из CDynFunException, таким образом сделать так чтобы можно было использовать код в программах WinAPI.
struct CDynFunException
{
    CDynFunException() : m_sMessage(0) {}
    CDynFunException(LPCTSTR sMessage) : m_sMessage(0)
    { SetMessage(sMessage); }
    CDynFunException(const CDynFunException &other) : m_sMessage(0)
    { SetMessage(other.sMessage); }
    CDynFunException &operator = (const CDynFunException &other)
    {
        SetMessage(other.sMessage);
        return *this;
    }
    ~CDynFunExecption()
    { delete[] m_sMessage; }

    const TCHAR* GetMessage() { return m_sMessage; }
private:
    void SetMessage(LPCTSTR sMessage)
    {
       delete[] m_sMessage;
       m_sMessage = new TCHAR[lstrlen(other.m_sMessage)+1];
       lstrcpy(m_sMessage,other.m_sMessage);
    }
    TCHAR* m_sMessage;
};


FunProxyThrowPolicy использует тоже CString, однако он выкидывает это как исключение.
Поэтому пользователю придется заботиться об уничтожении выделенной памяти или же сделать обертку для этого.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.