Если адрес функции не может быть разрешен во время вычета, это SFINAE или ошибка компилятора?
-
04-10-2019 - |
Вопрос
В 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
пытается быть вызванным.