enable_if + комбинация disable_if провоцирует неоднозначный звонок

StackOverflow https://stackoverflow.com/questions/3491848

  •  28-09-2019
  •  | 
  •  

Вопрос

Пытаясь ответить этот вопрос Я хотел предложить использование 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;
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top