Рассмотрим следующий код:
//Allows to automatically define post in/de-crement operators from their pre- version
template<typename T>
struct Arithmetic
{
//Not a template?
friend constexpr auto operator++(T& l, int)
{ auto old = l; ++l; return old; }
friend constexpr auto operator--(T& l, int)
{ auto old = l; --l; return old; }
};
//Only defines increment
struct Foo : Arithmetic<Foo>
{
int val;
Foo& operator++() { ++val; return *this; }
};
int main(int argc, char* argv[])
{
Foo f;
f.val = 12;
++f;
f++;
return 0;
}
Если бы я попытался определить оператор пост-декремента «вручную» (за пределами Arithmetic
), я получил бы ошибку на --l;
, потому что пред Оператор -определения не определен. Поскольку не шаблонные друзья шаблонных классов, по-видимому, не считаются шаблонными функциями, я ожидал бы того же поведения.
Но на самом деле код прекрасно компилируется для C ++ 17 (по крайней мере, для msv c и г cc). Почему это так? Является ли этот тип функции конкретным c случаем не шаблонной функции, которая все еще создается?
Какие части стандарта позволяют или запрещают мне делать такие вещи?