2

The following code illustrates a problem I have run into where it fails to compile with an undefined reference to Def::DEFAULT;

However if I comment out the 2nd line in main it will compile and run fine, I am able to "see" the value assigned to DEFAULT either through a cast to int or assigning to the Val class int data member directly.

template <typename T, T def>
class Def {
 public:
    static const T DEFAULT = def;
    enum {DEFAULT_ENUM = DEFAULT};
};


class Val {
 public:
    Val& operator=(const int &val_in) {
        val = val_in;
        return *this;
    }

    int val;
};


typedef Def<int, 10> Def_t;

Val test_val;

int main()
{
    test_val     =       Def_t::DEFAULT_ENUM;  // works
    test_val     =       Def_t::DEFAULT;       // fails to compile
    test_val     = (int) Def_t::DEFAULT;       // works
    test_val.val =       Def_t::DEFAULT;       // works
}
Zack3
  • 23
  • 3

1 Answers1

2

Your code has undefined behaviour because you are using Def_t::DEFAULT without ever defining it [basic.def.odr]/3:

Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program; no diagnostic required.

The declaration in the class definition is not a definition [class.static.data]/2:

The declaration of a static data member in its class definition is not a definition ... . The definition for a static data member shall appear in a namespace scope enclosing the member’s class definition. ...

If your code still does not compile when you add a declaration for Def_t::DEFAULT, then this is a bug in your compiler. The definition can be added by placing the following in namespace scope:

template<typename T, T def>
T const Def<T, def>::DEFAULT;

If you want this to work when T is not of integral or enumeration type, put the initialiser for DEFAULT in this namespace-scope definition rather than in the class definition.

Mankarse
  • 39,818
  • 11
  • 97
  • 141
  • Thank you very much for your explanation. Once I added the missing declaration the compiler error was gone and it runs fine. – Zack3 Apr 28 '13 at 03:38