enable_if + комбинация disable_if провоцирует неоднозначный звонок
Вопрос
Пытаясь ответить этот вопрос Я хотел предложить использование enable_if
+ disable_if
Чтобы разрешить перегрузку метода на основе того факта, что тип был (или нет) полиморфной.
Поэтому я создал небольшой тестовый файл:
template <class T>
void* address_of(T* p,
boost::enable_if< boost::is_polymorphic<T> >* dummy = 0)
{ return dynamic_cast<void*>(p); }
template <class T>
void* address_of(T* p,
boost::disable_if< boost::is_polymorphic<T> >* dummy = 0)
{ return static_cast<void*>(p); }
struct N { int x; };
int main(int argc, char* argv[])
{
N n;
std::cout << address_of(&n) << std::endl;
return 0;
}
который кажется довольно ручным.
Однако GCC (3.4 ...) задыхается на это:
test.cpp: в функции
int main(int, char**)
:
test.cpp: 29: Ошибка: вызов перегруженнойaddress_of(N*)
неоднозначно
Test.CPP: 17: Примечание: кандидаты:void* address_of(T*, boost::enable_if<boost::is_polymorphic<T>, void>*)
с t = n
TEST.CPP: 20: Примечание:void* address_of(T*, boost::disable_if<boost::is_polymorphic<T>, void>*)
с t = n
Мой человеческий разум кажется довольно ясно, какая перегрузка должна использоваться здесь. Я имею в виду, ясно, что я определил альтернативу, и только одна функция может быть использована одновременно ... и я бы подумал, что Sfinae позаботится о недействительности ненужной перегрузки.
Я исправил его, используя ...
(эллипсис) вместо disable_if
И требуя от манекена второго аргумента ... Но я все еще интересуюсь, почему компилятор заслонки этого.
Решение
Компилятор задохнул, потому что вы забыли трейлинг ::type
на enable_if
и disable_if
. Отказ Шаблоны всегда определены; Это просто тот, что член type
присутствует, если и только если выражение true
(за enable_if
) или false
(за disable_if
).
template <class T>
void* address_of(T* p,
типичка boost::enable_if< boost::is_polymorphic<T> >::тип* dummy = 0)
{ return dynamic_cast<void*>(p); }
template <class T>
void* address_of(T* p,
типичка boost::disable_if< boost::is_polymorphic<T> >::тип* dummy = 0)
{ return static_cast<void*>(p); }
Без трещины ::type
, ваши функции шаблоны просто создают перегрузки, которые принимают указатели на экземпляры enable_if
или disable_if
как второй параметр. С трейлингом ::type
, шаблоны либо создают перегрузку со вторым параметром типа void*
, или перегрузка удалена (т.е. желаемое поведение).
Другие советы
Использование версии «возвращаемого типа» ANABLE_IF работает в 3.4.4: gcc version 3.4.4 (cygming special, gdc 0.12, using dmd 0.125)
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_polymorphic.hpp>
#include <iostream>
template <class T>
typename boost::enable_if< boost::is_polymorphic<T>, void* >::type
address_of(T* p)
{ return dynamic_cast<void*>(p); }
template <class T>
typename boost::disable_if< boost::is_polymorphic<T>, void* >::type
address_of(T* p)
{ return static_cast<void*>(p); }
struct N { int x; };
int main(int argc, char* argv[])
{
N n;
std::cout << address_of(&n) << std::endl;
return 0;
}