Commands such as \{ are to be used with care because they are defined with \DeclareRobustCommand. The expansion of \{ is
\x@protect \{\protect \{
and this is a sure sign that using it in an x argument is doomed to failure.
You could redefine
\protected\def\{{\ifmmode \lbrace \else \textbraceleft \fi}
and it would work; in xparse parlance it would be
\DeclareDocumentCommand \{ { }
{
\mode_if_math:TF { \lbrace } { \textbraceleft }
}
and this would survive x expansion. One of the tasks waiting the LaTeX3 team is to redefine all such commands with ‘\protected’ macros instead of \DeclareRobustCommand. The reason is that \protected wasn't available when LaTeX2e was developed: it's one of the e-TeX extensions.
It would be a huge task to redefine all robust commands (\textbraceleft would need a rather different treatment). You can safely expand one level only, but probably you should take a different approach.
\documentclass{article}
\usepackage{expl3}
\begin{document}
\ExplSyntaxOn
\tl_new:N \__my_a_tl
\tl_new:N \__my_b_tl
\tl_new:N \__my_c_tl
\tl_set:Nn \__my_a_tl { test }
\tl_set:Nn \__my_b_tl { \{ }
\tl_put_right:Nx \__my_c_tl
{
\exp_not:N \m { \exp_not:V \__my_a_tl } { \exp_not:V \__my_b_tl }
}
\tl_show:N \__my_c_tl % expected result: \m{test}{\{}
\ExplSyntaxOff
\end{document}
Output on terminal:
> \__my_c_tl=macro:
->\m {test}{\{}.
\{doesn't survive\edef, so it can't appear where full expansion is made. In LaTeX3 (when fully available) it will. – egreg Nov 14 '13 at 23:36