Estimate  using Machin's formula
Answers to your questions

Is my use of enable_if_t appropriate and idiomatic?

Yes, it is appropriate, and I believe idiomatic for C++17 as well. In C++20 the idiomatic way would be to use concepts of course.

Is the use of static_cast for one_over_5 and one_over_239 the &quot;best&quot; solution here? Neccesary, and appropriate?

It's necessary to cast at least a few constants to ensure the expression has the right type. However, in this case I would use the constructor syntax instead, and only do it for the minimum number of constants necessary, to keep the expression concise and legible:
return (4 * arctan(T{1} / 5) - arctan(T{1} / 239)) * 4;

Also note that you don't need to specify &lt;T&gt; here, it can be automatically deduced, and since this is so short there is no need to declare temporary variables one_over_5 and one_over_239.

How about the use of decltype, ::epsilon and ::digits10?

The use of T::digits10 is fine here. However, using T::epsilon() is always very dangerous. It works here only because you are trying to calculate something close to 1, or if you wanted to calculate the arctangent from a very small number you have the advantage that \$\lim_{x\to 0} \arctan x = x\$. In general, if you want to calculate a value using some converging expansion and want to stop if further steps are no longer giving you any increase in precision, you can do that by checking if there is any change in the floating point value:
while (res + std::fabs(term) != res) {...}

Or perhaps using std::nextafter(), to keep in the spirit of T::epsilon():
while (res + std::fabs(term) &gt; std::nextafter(res, res + 1)) {...}

Although for std::nextafter(), it might even be hard to come up with the correct second argument.
Again, your method works fine in this case, it produces the same output as both methods above.

Accuracy: How about sign =* -1 and den += 2.0 and ... = sign * ...? These are integer operations but use the floating point type.

Currently those are floating point operations because the left hand side is a floating point type, and if the other side is an integer it would be promoted to the floating point type before the operation is performed. Note that you can replace all the constants in arctan() with integers and the result will still be correct.
You could change the type of sign and den to be an integer type, but it is not necessary. Multiplying floating point sign by -1 will not make it drift away from 1/-1 over time, and since integers up to \$2^{24}\$ can be represented exactly by a float, you will not have any problems with den either, unless the loop would run for more than 8388607 iterations, which would mean you have bigger problems.

My choice to force the user of pi() to specify a T?

It forces the user to give the correct type, which might result in less errors and/or more optimal code. You could consider making it double by default:
template &lt;typename T = double, ...&gt;
T pi() {...}

Note that C++20 introduces std::pi_v&lt;&gt; which also doesn't not have a default type.
Make the functions constexpr
You can and should make the functions constexpr. Interestingly, the compiler would be free to calculate the results of pi_float, pi_double and pi_long_double at compile time regardless, however GCC and Clang don't without constexpr. With constexpr, GCC does calculate the result at compile time, but Clang still emits a lot of code.