Consider the following code :
//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;
}
If I tried to define the post-decrement operator "manually" (outside of Arithmetic), I would get an error on --l; because the pre-decrement operator is not defined. As non-template friends of template classes are apparently not considered template functions, I would expect the same behaviour.
But as it is, the code compiles just fine for C++17 (at least on msvc and gcc). Why is that so? Is this kind of function a specific case of non-template function that still gets instanciated?
What parts of the standard allow or prevent me from doing such things?