non-type template parameters and overloading
От: Тот кто сидит в пруду Россия  
Дата: 08.12.09 14:03
Оценка: 32 (1)
Запрещает ли стандарт делать перегруженные функции с разными non-type template parameters? Перегружать специализации разрешает (14.5.5.1.1), отличать функции с non-type template parameters от функций с типовым параметром — тоже (14.5.5.1.4), а вот так можно?

template <BOOL (WINAPI * Destr)(HANDLE)> void DestroyHandle(HANDLE res)
{ Destr(res); }
template <LSTATUS (WINAPI * Destr)(HKEY)> void DestroyHandle(HKEY res)
{ Destr(res); }


Компилятор (VC 9) вроде непосредственно на объявление не ругается...

Зато дальше — вот при таком

void (*x)(HANDLE res) = &DestroyHandle<&FindClose>;


использовании не может отличить одну функцию от другой:

1>c:\projects\test141srlz\main.cpp(18) : error C2440: 'specialization' : cannot convert from 'BOOL (__stdcall *)(HANDLE)' to 'LSTATUS (__stdcall *const )(HKEY)'
1> This conversion requires a reinterpret_cast, a C-style cast or function-style cast
1>c:\projects\test141srlz\main.cpp(18) : error C2973: 'DestroyHandle' : invalid template argument 'BOOL (__stdcall *)(HANDLE)'
1> c:\projects\test141srlz\main.cpp(15) : see declaration of 'DestroyHandle'


Так действительно не положено делать или это просто компилятор убогий?
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Re: non-type template parameters and overloading
От: wander  
Дата: 08.12.09 14:17
Оценка: 1 (1)
Здравствуйте, Тот кто сидит в пруду, Вы писали:

ТКС>Запрещает ли стандарт делать перегруженные функции с разными non-type template parameters? Перегружать специализации разрешает (14.5.5.1.1), отличать функции с non-type template parameters от функций с типовым параметром — тоже (14.5.5.1.4), а вот так можно?


ТКС>
ТКС>template <BOOL (WINAPI * Destr)(HANDLE)> void DestroyHandle(HANDLE res)
ТКС>{ Destr(res); }
ТКС>template <LSTATUS (WINAPI * Destr)(HKEY)> void DestroyHandle(HKEY res)
ТКС>{ Destr(res); }
ТКС>


ТКС>Компилятор (VC 9) вроде непосредственно на объявление не ругается...


ТКС>Зато дальше — вот при таком


ТКС>
ТКС>void (*x)(HANDLE res) = &DestroyHandle<&FindClose>;
ТКС>


ТКС>использовании не может отличить одну функцию от другой:


ТКС>

1>>c:\projects\test141srlz\main.cpp(18) : error C2440: 'specialization' : cannot convert from 'BOOL (__stdcall *)(HANDLE)' to 'LSTATUS (__stdcall *const )(HKEY)'
1>> This conversion requires a reinterpret_cast, a C-style cast or function-style cast
1>>c:\projects\test141srlz\main.cpp(18) : error C2973: 'DestroyHandle' : invalid template argument 'BOOL (__stdcall *)(HANDLE)'
1>> c:\projects\test141srlz\main.cpp(15) : see declaration of 'DestroyHandle'


ТКС>Так действительно не положено делать или это просто компилятор убогий?


С компилятором все нормально. Ты посмотри, чем на само деле являются HANDLE и HKEY и станет понятно все сразу.
Re[2]: non-type template parameters and overloading
От: Тот кто сидит в пруду Россия  
Дата: 08.12.09 14:24
Оценка: 1 (1)
Здравствуйте, wander, Вы писали:

W>С компилятором все нормально. Ты посмотри, чем на само деле являются HANDLE и HKEY и станет понятно все сразу.


Они, естественно, разные. Так что мимо:

template <BOOL (WINAPI * Destr)(HANDLE)> void DestroyHandle(HANDLE res)
{ Destr(res); }
template <LSTATUS (WINAPI * Destr)(double)> void DestroyHandle(double res)
{ Destr(res); }

void (*x)(HANDLE res) = &DestroyHandle<&FindClose>;


1>c:\projects\test141srlz\main.cpp(18) : error C2440: 'specialization' : cannot convert from 'BOOL (__stdcall *)(HANDLE)' to 'LSTATUS (__stdcall *const )(double)'
1> This conversion requires a reinterpret_cast, a C-style cast or function-style cast
1>c:\projects\test141srlz\main.cpp(18) : error C2973: 'DestroyHandle' : invalid template argument 'BOOL (__stdcall *)(HANDLE)'
1> c:\projects\test141srlz\main.cpp(15) : see declaration of 'DestroyHandle'

Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Re[3]: non-type template parameters and overloading
От: wander  
Дата: 08.12.09 14:31
Оценка:
Здравствуйте, Тот кто сидит в пруду, Вы писали:

ТКС>Здравствуйте, wander, Вы писали:


W>>С компилятором все нормально. Ты посмотри, чем на само деле являются HANDLE и HKEY и станет понятно все сразу.


ТКС>Они, естественно, разные.

Это в MSVC они разные, а у меня (mingw) вот, например, одинаковые. Но проблема все равно не в этом.
ТКС>Так что мимо:
Мимо. Согласен.

ТКС>
ТКС>template <BOOL (WINAPI * Destr)(HANDLE)> void DestroyHandle(HANDLE res)
ТКС>{ Destr(res); }
ТКС>template <LSTATUS (WINAPI * Destr)(double)> void DestroyHandle(double res)
ТКС>{ Destr(res); }

ТКС>void (*x)(HANDLE res) = &DestroyHandle<&FindClose>;
ТКС>


ТКС>

1>>c:\projects\test141srlz\main.cpp(18) : error C2440: 'specialization' : cannot convert from 'BOOL (__stdcall *)(HANDLE)' to 'LSTATUS (__stdcall *const )(double)'
1>> This conversion requires a reinterpret_cast, a C-style cast or function-style cast
1>>c:\projects\test141srlz\main.cpp(18) : error C2973: 'DestroyHandle' : invalid template argument 'BOOL (__stdcall *)(HANDLE)'
1>> c:\projects\test141srlz\main.cpp(15) : see declaration of 'DestroyHandle'


А такой код будет у тебя работать ?

template <int (* Destr)(void*)>
void DestroyHandle(void* res)
{ Destr(res); }

template <bool(* Destr)(void*)>
void DestroyHandle(void* res)
{ Destr(res); }


int d1(void*)
{
    return 0;
}

bool d2(void*)
{
    return 1;
}

int main()
{
    void (*x)(void *) = &DestroyHandle<&d2>;

    x(0);
}


Mingw 4.4 компилит. Исполняется как того и ожидается.
Re[4]: non-type template parameters and overloading
От: Тот кто сидит в пруду Россия  
Дата: 08.12.09 14:36
Оценка:
Здравствуйте, wander, Вы писали:

W>А такой код будет у тебя работать ?


W>
W>template <int (* Destr)(void*)>
W>void DestroyHandle(void* res)
W>{ Destr(res); }

W>template <bool(* Destr)(void*)>
W>void DestroyHandle(void* res)
W>{ Destr(res); }


W>int d1(void*)
W>{
W>    return 0;
W>}

W>bool d2(void*)
W>{
W>    return 1;
W>}

W>int main()
W>{
W>    void (*x)(void *) = &DestroyHandle<&d2>;

W>    x(0);
W>}
W>


W>Mingw 4.4 компилит. Исполняется как того и ожидается.


Та же ошибка:

1>c:\projects\test141srlz\main.cpp(51) : error C2440: 'specialization' : cannot convert from 'bool (__cdecl *)(void *)' to 'int (__cdecl *const )(void *)'
1> This conversion requires a reinterpret_cast, a C-style cast or function-style cast
1>c:\projects\test141srlz\main.cpp(51) : error C2973: 'DestroyHandle' : invalid template argument 'bool (__cdecl *)(void *)'
1> c:\projects\test141srlz\main.cpp(31) : see declaration of 'DestroyHandle'
1>c:\projects\test141srlz\main.cpp(51) : error C2440: 'initializing' : cannot convert from 'overloaded-function' to 'void (__cdecl *)(void *)'
1> None of the functions with this name in scope match the target type

Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Re[5]: non-type template parameters and overloading
От: wander  
Дата: 08.12.09 14:39
Оценка:
Здравствуйте, Тот кто сидит в пруду, Вы писали:

ТКС>Та же ошибка:


Стандарта под рукой нет. Но сдается мне, все-таки, компилятор убогий
Re: non-type template parameters and overloading
От: Кодт Россия  
Дата: 09.12.09 17:18
Оценка:
Здравствуйте, Тот кто сидит в пруду, Вы писали:

ТКС>Запрещает ли стандарт делать перегруженные функции с разными non-type template parameters? Перегружать специализации разрешает (14.5.5.1.1), отличать функции с non-type template parameters от функций с типовым параметром — тоже (14.5.5.1.4), а вот так можно?


Попробовал с более простыми типами.
VC8 и VC9 заругались, g++ 3.4.4 съел
#include <iostream>

#define __FUNCSIG__ __PRETTY_FUNCTION__

template<int* p>        void foo() { std::cout << __FUNCSIG__ << " " << *p << std::endl; } // (1)
template<char* p>       void foo() { std::cout << __FUNCSIG__ << " " <<  p << std::endl; } // (2)
template<const char* p> void foo() { std::cout << __FUNCSIG__ << " " <<  p << std::endl; } // (3)

int x = 12345;
char y[] = "hello";
extern const char z[] = "world"; // без extern подразумевается static, ибо const

int main()
{
    foo<&x>();
    foo<y>(); // неоднозначность между (2) и (3); стоит закомментировать любую - неоднозначность исчезнет
    foo<z>(); // естественно, закомментировать (3) означает создать ошибку здесь
}
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Перекуём баги на фичи!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.