Thursday, January 12, 2012

gcc error: invalid use of member (did you forget the `&' ?)

Every time I have gotten the above compilation error, it has nothing to do with a missing ampersand. Instead, it is missing function-call parentheses:

  if (you_go && use->yourMember) { // WRONG!
    this->isInvalid();
  }

  if (i_go && use->myMember()) { // Oh yeah, the parens.
    continue;
  }

So don't use your member invalidly.


Stumble Upon Toolbar

Friday, March 11, 2011

Don't Avoid No-ops

A form of spurious case analysis that seems to come up a lot in the code I have to work on right now falls under the category of "avoiding a no-op". Well, don't add cruft to your code just to avoid a no-op.

Here's the one that I see hundreds of:

  if (ptr != NULL) {
    delete ptr;
  }
Instead of:
  delete ptr;
But the line that caused me to post this today was this:
  if (!isalnum(str[i]) && (str[i] != '_')) str[i] = '_';
Why complicate the if condition just to make sure and not overwrite an underscore with an underscore? In reading through this code I paused to consider when an underscore could occur, and whether something special had to happen, only to read a little further and see that someone was guarding against a no-op. Good lord, just perform the no-op so I can read this more easily:
  if (!isalnum(str[i])) str[i] = '_';


Stumble Upon Toolbar

Thursday, January 27, 2011

Filename Expansion in Tcl

Stupid, stupid, Tcl. If you want to run a shell command with a glob filename, like *.h, you can't just do:

exec ls -l *.h

You have to explicitly tell Tcl to expand the glob, because it will pass *.h to the shell literally. But you also can't do:
exec ls -l [glob *.h]

because it will pass the entire list to the shell literally (thanks, Tcl, that's useful). You get lucky and it works if there is exactly one file matched by the glob. Otherwise ls will complain that there's no file called "a.h b.h c.h".

So what do you do? Unfortunately, if you pull up the man page for exec on the internet, it tells you a way to do this that is only syntactically valid for Tcl 8.5 or greater. For those of us living in the past, the demonic incantation you must utter is:
eval [list exec ls -l] [glob *.h]

Don't use Tcl unless you have to.


Stumble Upon Toolbar

Wednesday, January 26, 2011

C++ Static No Longer Deprecated

Wow, a long-held piece of geek trivia is no longer true.

This Stack Overflow article points out that in a recent draft of the upcoming C++0x revision to the C++ standard, file-scope static declarations are no longer deprecated. For, oh, 20 years, it's been one of those finer language points that you can whip out to show your sophistication and look down on the ignorant. But between the August 2010 draft (pdf) and the November 2010 draft (pdf), the section deprecating static has been struck!

If you're unfamiliar with the issue, it's that anonymous namespaces provide a more general solution to the multiply-defined symbol problem. Instead of:


static int num = 0;
static int read_num() { return num; }


the preferred C++ way to limit visibility of global objects to file scope was:


namespace {

int num = 0;
int read_num() { return num; }

} // anonymous namespace


The rationale is that you can put other symbols you wish to hide -- like class definitions -- in such a namespace, but static doesn't help you with those. As the most general solution to the problem, namespace wins and static loses. But I suppose that 20 years of failing to break people of the static habit led to a recent change of heart.

Suits me. I had been consistently using anonymous namespaces for quite a while, both to be modern and especially since it does frequently come up that I want a type that is only used in one file. But static declarations are better for self-documenting the code, so I am happy to welcome them back.

Only problem is, I need a new piece of C++ trivia to show off with.


Stumble Upon Toolbar

Wednesday, November 17, 2010

Emacs: Copy Environment Variable from Shell

Sometimes I get annoyed when my emacs session has different environment variable settings than some shell buffer I have running in the session. The most painful is when a Makefile depends on environment settings that I don't have in my .profile. Command-name completion in a shell buffer can also be painful if you have changed your path. And of course I'd like gdb to start up with the correct environment every time -- you can set the variables inside gdb, but that gets old on those days when gdb itself crashes again and again.

I kept pasting export FOO=bar into the *scratch* buffer and editing it into (setenv "FOO" "bar") and eval'ing that. After the 1000th time of doing that, I decided to automate it. Turns out emacs already has an interactive function for copying an environment variable from the shell, but you have to type in the variable name. I decided to write a little function to look for the last export, or the last echo $FOO, and copy that variable:

(defun engisneering-shell-copy-env-var ()
  (interactive)
  (let* ((expat "\\(export +\\([^=\n]+\\)=\\(.+\\)\\)")
         (echpat "\\(echo +\\$\\(.+\\)\n\\(.+\\)\\)")
         (cshpat "\\(setenv +\\([^ \n]+\\) +\\(.+\\)\\)")
         (patt (concat shell-prompt-pattern
                       "\\(" expat "\\|" echpat "\\|" cshpat "\\)")))
    (save-excursion
      (if (re-search-backward patt)
          (let* ((m (or (and (match-beginning 2) 3)
                        (and (match-beginning 5) 6) 9))
                 (var (buffer-substring (match-beginning m) (match-end m)))
                 (oldval (or (getenv var) " ")))
            (shell-copy-environment-variable var)
            (setq val (getenv var))
            (message "Old %s=%s; New %s=%s" var oldval var val))))))

Run this function inside your shell buffer, and it will search backwards for the last environment variable action and bring that variable setting into the emacs session. It's also nice because it gives you a message in the minibuffer showing the change. Add a local-set-key -- I like C-c C-v -- in your shell-mode-hook, and you're good to go.


Stumble Upon Toolbar

Wednesday, September 22, 2010

Let's Allocate Stuff!

Nobody's perfect, of course, but when there are so many things wrong with a small piece of C++ code, it's hard to be placid. How about:

  std::vector v = new std::vector;
  // ...
    v->push_back(new std::string("..."));
  // ...
  std::ostream *str = get_me_a_stream(...);
  for (int i = 0; i < v->size(); i++) {
    *str << (*v)[i]->c_str();
  }
  delete str;
  // loop to delete v and its elements.

Ow, my head is spinning from all of these needless allocations. Let's not wear out new and delete.

Well, if you first learn C and then learn C++, your head might still be in Pointer Land. But the unnecessary call to c_str() makes it hard for me to get any work done.


Stumble Upon Toolbar

Saturday, August 14, 2010

gcc: error: expected `)' before '&' token

Duplicate post here just to get two related error messages into page titles. That's as much SEO as I know how to do.

If you get this error from g++, and everything looks correct to you, maybe you are defining a constructor without qualifying it with the class name. See the example on this post.


Stumble Upon Toolbar