Если адрес функции не может быть разрешен во время вычета, это SFINAE или ошибка компилятора?

В C++ 0x SFINAE правила были упрощены таким образом, что любое недопустимое выражение или вводит, который происходит в "прямом контексте" вычета, не приводит к ошибке компилятора, а скорее к отказу вычета (SFINAE).

Мой вопрос - это:
Если я беру адрес перегруженной функции, и он не может быть разрешен, то, что отказ в прямом контексте вычета?
(т.е. действительно ли это - серьезная ошибка или SFINAE, если это не может быть разрешено)?

Вот некоторый пример кода:

struct X
{
  // template<class T> T* foo(T,T); // lets not over-complicate things for now
  void foo(char);
  void foo(int);
};


template<class U> struct S
{
  template<int> struct size_map 
  { typedef int type; };


// here is where we take the address of a possibly overloaded function
  template<class T> void f(T, 
      typename size_map<sizeof(&U::foo)>::type* = 0); 


  void f(...);
};

int main()
{
  S<X> s;

// should this cause a compiler error because 'auto T = &X::foo' is invalid?
  s.f(3);  

}

Gcc 4.5 указывает, что это - ошибка компилятора, и лязг выкладывает нарушение утверждения.

Вот еще некоторые связанные вопросы интереса:

FCD-C++ 0x ясно указывают то, что должно произойти здесь?
Находятся компиляторы неправильно в отклонении этого кода?
"Прямой контекст" вычета должен быть определен немного лучше?

Спасибо!

23
задан Johannes Schaub - litb 2 October 2011 в 10:29
поделиться

1 ответ

template<class T> void f(T, 
    typename size_map<sizeof(&U::foo)>::type* = 0); 

Это не работает, потому что U не участвует в дедукции. Хотя U является зависимым типом, при выводе для f он рассматривается как фиксированный тип с независимым именем. Вам необходимо добавить его в список параметров f

/* fortunately, default arguments are allowed for 
 * function templates by C++0x */
template<class T, class U1 = U> void f(T, 
    typename size_map<sizeof(&U1::foo)>::type* = 0); 

. В вашем случае, поскольку U :: foo не зависит от параметров самого f , вы получите ошибка при неявном создании экземпляра S (попробуйте закомментировать вызов, и он все равно не удастся). FCD говорит в 14.7.1 / 1

Неявное создание экземпляра специализации шаблона класса вызывает неявное создание экземпляров объявлений, но не определений или аргументов по умолчанию, функций-членов класса, классов-членов, статических элементы данных и шаблоны элементов;

То есть, если вы неявно создаете экземпляр S , будет создано следующее объявление шаблона функции

template<class T> void S<X>::f(T, 
  typename size_map<sizeof(&X::foo)>::type* = 0); 

Анализ этого объявления шаблона затем обнаружит, что он не может разрешить ссылку на X :: foo и вывести ошибку. Если вы добавите U1 , объявление шаблона еще не будет пытаться разрешить ссылку на U1 :: foo (поскольку U1 является параметром f ), и, таким образом, останется действительным и SFINAE при попытке вызова f .

29
ответ дан 29 November 2019 в 02:39
поделиться
Другие вопросы по тегам:

Похожие вопросы: