комбинация enable_if + disable_if провоцирует неоднозначный вызов - PullRequest
5 голосов
/ 16 августа 2010

Пытаясь ответить на этот вопрос Я хотел предложить использовать 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 и требуя фиктивного второго аргумента ... но мне все еще интересно, почему компилятор подавился этим.

Ответы [ 2 ]

11 голосов
/ 16 августа 2010

Компилятор захлебнулся, потому что вы забыли завершающий ::type на enable_if и disable_if.Шаблоны всегда определены;просто член type присутствует тогда и только тогда, когда выражение равно true (для enable_if) или false (для disable_if).

template <class T>
void* address_of(T* p,
                 <strong>typename</strong> boost::enable_if< boost::is_polymorphic<T> ><strong>::type</strong>* dummy = 0)
{ return dynamic_cast<void*>(p); }

template <class T>
void* address_of(T* p,
                 <strong>typename</strong> boost::disable_if< boost::is_polymorphic<T> ><strong>::type</strong>* dummy = 0)
{ return static_cast<void*>(p); }

Без завершающего::type, ваши шаблоны функций просто создают перегрузки, которые принимают указатели на экземпляры enable_if или disable_if в качестве второго параметра.При завершающем ::type шаблоны либо создают перегрузку со вторым параметром типа void*, либо перегрузка удаляется (т.е. желаемое поведение).

0 голосов
/ 16 августа 2010

Использование версии типа enable_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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...