views:

704

answers:

4

I have a template matrix class class defined in a header called "Matrix.h".

Certain matrices are used repeatedly in my program. I thought that I would define these in the "Matrix.h" header file, like so:

const Matrix<GLfloat> B_SPLINE_TO_BEZIER_MATRIX(4, 4, values);

When I do this g++ complains that I redefined the constant in question. This happens because I include Matrix.h in two different source files. When the object files for these are compiled, both end up with a definition of the matrix above, causing the error message.

My question is how do I avoid this situation? I want a constant that is accessible to more than one file, but I don't know where to put it.

+8  A: 

You avoid it by:

  • Declaring it extern in the header. A symbol can be declared any number of times.
  • Defining it in the implementation, only once.
unwind
The problem with this is that I don't have an implementation file. It's a template class, so it doesn't generate a .o file. For this reason I don't make .C files for templates.
fluffels
So - just add an implementation file (!) That *will* generate a .o file, with just the single B_SPLINE_TO_BEZIER_MATRIX definition in it.
MSalters
+5  A: 

If you don't want to split it between a header and implementation file,

  1. Declare your constant static (or declare it in anonymous namespace) to make definition private. Linker will not complain, but it will result in multiple private copies across compilation units.

    static Matrix<GLfloat> B_SPLINE_TO_BEZIER_MATRIX(4, 4, values);
    
  2. Make an inline function that returns the constant. Inline function definitions produce "weak" symbols in object file, so linker will eliminate duplicates and pick one.

    inline const Matrix<GLfloat>&
    GET_B_SPLINE_TO_BEZIER_MATRIX() {
        const static Matrix<GLfloat> B_SPLINE_TO_BEZIER_MATRIX(4, 4, values);
        return B_SPLINE_TO_BEZIER_MATRIX;
    }
    
Alex B
Thanks a lot! The "static" keyword made all my problems go away :)
fluffels
It's deprecated in favor of namespace { } though.
MSalters
And the second one in fact will not result in multiple copies: 7.1.2/4 "A static local variable in an extern inline function always refers to the same object. "
MSalters
@MSalters: Though there can only be one `namespace {}` per compilation unit, so `static` is safer.
rlbond
Really? I can compile a C++ file with multiple anonymous namespaces. Care to elaborate?
Alex B
A: 

just write your header file like this

#ifndef HEADER_FILE_NAME_H

#define HEADER_FILE_NAME_H

// your header file code

#endif

this will make sure that it won't get declared multiple times

serioys sam
This helps for not including a header file twice during the same run of the compiler. But remember that it's 2 different source files, so g++ runs on each of them separately.
fluffels
Read question most carefully before answering.
bb
A: 

Wrap header files (.h) in preprocessor conditionals to prevent them from being included in the compiler's symbol table twice:

#ifndef HEADER_NAME
#define HEADER_NAME
// code...
#endif//HEADER_NAME

HEADER_NAME can really be anything, but it's best to make sure that it's something related to the file to prevent more collisions, as this is just defining an empty preprocessor macro (which also ends up in the symbol table).

Read question most carefully before answering.
bb
This helps for not including a header file twice during the same run of the compiler. But remember that it's 2 different source files, so g++ runs on each of them separately.
fluffels
Ah, reading comprehension ftw. I'd personally go with static in that case.