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

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

Вопрос

В 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 заявляет, что это ошибка компилятора, а Clang выпивает нарушение утверждения.

Вот несколько более связанных вопросов, представляющих интерес:

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

Спасибо!

Это было полезно?

Решение

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<X> (Попробуйте прокомментировать звонок, и все равно должен потерпеть неудачу). FCD говорит на 14.7.1/1

Неявное представление о специализации шаблона класса класса приводит к тому, что неявное зовутное мнение деклараций, но не от определений или дор.

То есть, если вы неявно создаете S<X> Следующая декларация шаблона функции будет создана

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 пытается быть вызванным.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top