C++ Templates and Emacs: Customizing Indentation

The best solution that I have found is writing a custom (and relatively straightforward) indentation function.

The Code

(defun c++-template-args-cont (langelem)
"Control indentation of template parameters handling the special case of '>'.
Possible Values:
0   : The first non-ws character is '>'. Line it up under 'template'.
nil : Otherwise, return nil and run next lineup function."
  (save-excursion
    (beginning-of-line)
    (if (re-search-forward "^[\t ]*>" (line-end-position) t)
        0)))

(add-hook 'c++-mode-hook
          (lambda ()
            (c-set-offset 'template-args-cont
                          '(c++-template-args-cont c-lineup-template-args +))))

This handles all of the cases that I have come across even with templates nested several levels deep.

How It Works

For indenting code, if a list of indentation functions is provided, then Emacs will try them in order and if the one currently being executed returns nil, it will invoke the next one. What I have done is added a new indentation function to the beginning of the list that detects whether the first non-whitespace character on the line is ‘>’, and if it is, set the indentation to position 0 (which will line it up with the opening template). This also covers the case where you have template-template parameters as follows:

template <
  template <
    typename T,
    typename U,
    typename... Args
  > class... CS
>

because it doesn’t care what’s after the ‘>’. So as a result of how the list of indentation functions works, if ‘>’ is not the first character, the function returns nil and the usual indentation function gets invoked.

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)