2024-09-10

ODR? Fuggedaboutit!

I was hacking together a thin patch at work today. Tyring to get the logging calls from a library to play nice with the rather hacky logging infrastructure of a legacy project we maintain. Basic translation worked fine, build support took a couple of tries but seemed to be coming together, but then there was the matter of Level enum and getting string representations for the values ... so I shoved a copy of the original enum and a definition of levelText(Level level) into the header.

Yeah, the definition. In the header. I should've know better being, as I allege I am, a big-boy programmer. Well, nature took it's course and the compiler complained: I was violating the One-Definition Rule (oh, holy of holies!) on a massive scale.

But I was ready to go to lunch and I didn't want to deal with hard problems like where in the project tree to put the source file that ought to hold the implementation and how to add it to the build system and so on. It was at this point that some rebel-without-a-cause, burn-it-all-down inner-self threw up a suggestion: why not try something like:

template <int=0>
std::string levelText(Level level) 
{ 
    /*...*/ 
}

I mean, what could it hurt?

Rhetorical question, of course, but let's list some of the failing of this cutesy little trick (which compiles):

Hacky, non-idiomatic, confusing
Any C++ prgrammer who sees a template declaration will expect you to do something with the template parameter, which we don't. Time will be spent look for the use and trying to suss out what the paramter might mean. Worse, if they're experienced they'll notice that it's a non-type parameter and be expecting some kind of clever (read tricky) metaprogramming, which there isn't.
Contibutes to slow build times
Evey template read takes a little more time and little more working set. So does every template instantiated. I menetioned that this is a legacy project, right? It already takes 12-15 minutes to build on a fast hexacore machine with lots of memory.
Contributes to bloated binaries
Every template instantiation creates a separate bit of code. We're writing that function for every source file that includes the header.

Once I'm fueled back up I can go back to the office and do it right. But now I know a new stupid C++ trick. Yeah!

No comments:

Post a Comment