Part of the special treatment of single characters in accent placement is the handling of sub- and superscripts. From the TeXbook, p. 443, Rule 12:
If the nucleus is a single character, replace box x
[which contains the nucleus in style C'
] by a box containing the nucleus together with the superscript and subscript of the Acc atom, in style C
, and make the sub/superscripts of the Acc atom empty; ...
Roughly speaking, the effect is that in \hat{a}^H
, the H
is "attached" to the a
, whereas in \hat{\kern0pt a}^H
it is "attached" to \hat{\kern0pt a}
and thus placed quite a bit higher. Here's an \ifsingle
command (with a true- and a false-branch), based on this idea. First the output:

\documentclass{article}
\newcommand*\ifsingle[3]{%
\setbox0\hbox{$\mathaccent"0362{#1}^H$}%
\setbox2\hbox{$\mathaccent"0362{\kern0pt#1}^H$}%
\ifdim\ht0=\ht2 #3\else #2\fi
}
\newcommand*\test[1]{$#1$ is\ifsingle{#1}{}{ not} a single character\par}
\newcommand*\stupida{\string a}
\newcommand*\awithbraces{a{}}
\begin{document}
\test{a}
\test{\alpha}
\test{\mathcal{A}}
\test{ab}
\test{a_1}
\test{\hat{a}}
\test{\stupida}
\test{\awithbraces}
\end{document}
As egreg points out in the comments, \ifsingle
does not identify [
, \sum
, ,
and +
as single characters. (And I modified the code so that =
isn't identified as single, either.) However, I think this is not a big deal: in \hat{=}
, the \hat
doesn't see a single character, either, since {=}
is not a single character. Only in \hat=
, the \hat
sees the single character =
. See this awesome answer by Frank Mittelbach for details.