I have the following in my .emacs file:
(defun c++-mode-untabify ()
(save-excursion
(goto-char (point-min))
(while (re-search-forward \"[ \\t]+
write-contents-hooks is also obsolete. This is what you're after:
(add-hook 'c++-mode-hook
'(lambda ()
(add-hook 'before-save-hook
(lambda ()
(untabify (point-min) (point-max))))))
This is distilled from what I use, which does a few other things and is abstracted out to work with programming-specific modes:
(defun untabify-buffer ()
"Untabify current buffer"
(interactive)
(untabify (point-min) (point-max)))
(defun progmodes-hooks ()
"Hooks for programming modes"
(yas/minor-mode-on)
(add-hook 'before-save-hook 'progmodes-write-hooks))
(defun progmodes-write-hooks ()
"Hooks which run on file write for programming modes"
(prog1 nil
(set-buffer-file-coding-system 'utf-8-unix)
(untabify-buffer)
(copyright-update)
(maybe-delete-trailing-whitespace)))
(defun delete-trailing-whitespacep ()
"Should we delete trailing whitespace when saving this file?"
(save-excursion
(goto-char (point-min))
(ignore-errors (next-line 25))
(let ((pos (point)))
(goto-char (point-min))
(and (re-search-forward (concat "@author +" user-full-name) pos t) t))))
(defun maybe-delete-trailing-whitespace ()
"Delete trailing whitespace if I am the author of this file."
(interactive)
(and (delete-trailing-whitespacep) (delete-trailing-whitespace)))
(add-hook 'php-mode-hook 'progmodes-hooks)
(add-hook 'python-mode-hook 'progmodes-hooks)
(add-hook 'js2-mode-hook 'progmodes-hooks)
Try adding your hook like this:
(add-hook 'c++-mode-hook
'(lambda ()
(add-hook 'write-contents-hooks 'c++-mode-untabify nil t)))
Notice the two extra aguments to add-hook. If I'm reading it right, according to the documentation that trailing t should do what make-local-hook does (or visa versa), but I've also seen references to make-local-hook being deprecated. At least on my box (linux, gnu emacs 21.3.1) I'm seeing the effect you want -- the hook is only attached to c++ buffers and not all the others.
As a last resort you could always put a check in your c++-mode-untabify function to only do it's magic if the current major mode is c++-mode.
This is a curious solution, however. If you remove all the tabs, what are you doing to put the tabs back in? If you stop whatever that is you won't need this hack.
The documentation in my Emacs says that make-local-hook is now obsolete as of 21.1, since add-hook now takes an optional argument for making a hook buffer-local. So you could try:
(add-hook 'c++-mode-hook
'(lambda ()
(add-hook 'write-contents-hooks 'c++-mode-untabify nil t)))
Another option is to have the c++-mode-untabify function check the current mode. I'd probably just write that as something like:
(defun c++-mode-untabify ()
(if (string= (substring mode-name 0 3) "C++")
(save-excursion
(delete-trailing-whitespace)
(untabify (point-min) (point-max)))))