EDIT: I just noticed a glitch in your code. You used selfadjoint and triangular. Try this:
The rest of my answer may still be useful, so I won't delete it.
Presumably, $L$ uses the column-major storage order. If not, just swap row for column everywhere in this post.
$L^T$ can be represented by casting $L$ as a row-major sparse matrix. This will store $L^T$ in the upper half.
Eigen::SparseMatrix<double,Eigen::RowMajor>::Map LT(L.cols(), L.rows(), L.nonZeros(), L.outerIndexPtr(), L.innerIndexPtr(), L.valuePtr());
VectorX<double> x = LT.triangularView<Upper>().solve(b);
This should avoid any copies as it just passes pointers to L's data. Although Eigen doesn't support RowMajor matrices for all its solvers, it does support the triangular solver. Also, this trick is very handy for when you want to use something like MKL which only supports RowMajor sparse matrices. If your matrix is symmetric...who cares if you're storing A or A^T!