You have not declared it as class. Your template parameter declaration
class = enable_if<IsCharType<CharType>::value>::type
is a declaration of an unnamed type parameter. We can give this parameter an explicit name, e.g.
class U = enable_if<IsCharType<CharType>::value>::type
So in this case it is U
that is declared as type parameter ("as class").
Meanwhile, everything to the right of =
is not "declared as class". It is interpreted by the compiler in accordance with general rules, without any regard to the fact that it happens to be a default argument for a type parameter.
Logic like "since this is a default argument for a type parameter, the compiler must realize by itself that this is a type" does not apply here simply because the language specification does not say it applies. Moreover, the language standard actually says
A name used in a template declaration or definition and that is dependent on a template-parameter is assumed not to name a type unless the applicable name lookup finds a type name or the name is qualified by the keyword typename.
This means that the compiler is required to assume that
enable_if<IsCharType<CharType>::value>::type
is not a type, which is contrary to what you expect it to do.
The language does have a number of contexts where dependent name is unconditionally assumed to name a type. That includes constructor initializer lists, base class specifiers and elaborated type specifiers. But default arguments for template type parameter is not one of such contexts.
SFINAE does not save the situation here. SFINAE, as the name suggests, works at the time of substitution. Your code never gets to substitution, it breaks much earlier. It is simply an invalid template definition.