#include <type_traits>
template<bool condition>
struct X {
template<std::enable_if_t<condition, bool> = true>
using MaybeInt = int;
template<std::enable_if_t<condition, bool> = true>
static MaybeInt<> MaybeResult() {
return 0;
}
};
int main() {
return X<true>::MaybeResult();
}
Is it possible to use the X<true>::MaybeInt
type without the empty angle brackets at the end? If not, why?
If I just remove them at line 9, clang++ in C++17 gives me the following error:
main.cpp:9:12: error: use of alias template 'MaybeInt' requires template arguments; argument deduction not allowed in function return type
static MaybeInt MaybeResult() {
^~~~~~~~
main.cpp:6:5: note: template is declared here
using MaybeInt = int;
^
1 error generated.
Why isn't that allowed?
No, leaving out the template argument list on a class or alias template's name has a different meaning than an empty template argument list on it would have.
With an empty template argument list, the whole thing names a single type that is the specialization obtained by using all default template arguments for the template parameters.
Without a template argument list, the name indicates to the compiler that class template argument deduction (CTAD) is to be done to determine the template arguments.
As the compiler is telling you however, CTAD is only permitted in certain context and a function return type is not one of them.
Even if CTAD was permitted in the context, it wouldn't work here, because your alias template doesn't satisfy the single specific form that is permitted for CTAD, which is satisfied basically only by alias templates that one-to-one alias a class template with the same template parameters/arguments.
Also your SFINAE attempt won't work. In order for SFINAE to apply your condition must be dependent on a template parameter of that template, not the enclosing class template.
When you try to instantiate X<false>
, the whole instantiation will fail because it tries to form an invalid type in the enable_if
. It won't only remove the declarations.