3

I'm having a weird problem where code that is compiled with -Ox compiles fine, but code that is compiled with -g fails on link with the following error:

Undefined symbols for architecture x86_64:
  "stupid<dummy>::t", referenced from:
      stupid<dummy>::operator()(int, int) const in main.o

The code that reproduces this problem:

struct dummy { void operator()(const int a, const int b) const {} ; };

template <typename  T>
struct stupid {
 constexpr static T t = T(); // create a new one;

 stupid() {};
 void operator()(int a, int b) const { t(a, b); }
};


int main()
{
 const stupid<dummy> a;
 a( 1, 2 );
}

It appears that when the code is optimized, the function is inlined and no external function call is asked for, but when the code is NOT optimized, the function is called but isn't there? (I'm not sure why it isn't there...). This happens in g++ 4.7 and 4.8 and clang 3.2.

Any ideas?

ildjarn
  • 62,044
  • 9
  • 127
  • 211
Andrew Spott
  • 3,457
  • 8
  • 33
  • 59

1 Answers1

1

You can get around this by adding

template<typename T> constexpr const T stupid<T>::t;

after the definition of stupid.

This is because calling a non-static member function of t requires that the address of t be taken to use as the this pointer. Taking the address of an object makes it require a runtime instance, which requires the above definition.

Vaughn Cato
  • 63,448
  • 5
  • 82
  • 132
  • thanks! any idea why it is happening? – Andrew Spott Mar 17 '13 at 00:38
  • @AndrewSpott: Basically, the program is ill-formed, because `t` is odr-used, but the linker is not required to produce a diagnostic for this error. So it may or may not, but the program is still ill-formed. See [this](http://stackoverflow.com/questions/14547986/what-am-i-allowed-to-do-with-a-static-constexpr-in-class-initialized-data-memb) – Andy Prowl Mar 17 '13 at 00:46
  • @AndyProwl: What is "odr-used"? – Andrew Spott Mar 17 '13 at 01:01
  • @AndrewSpott: I've added some explanation. See if it is clearer now. – Vaughn Cato Mar 17 '13 at 01:24
  • @VaughnCato: So, my original guess was kind of correct? When optimizations are turned on, the function is inlined, and thus no error, but when optimizations aren't on, the address of `t` must be taken, but it doesn't exist... – Andrew Spott Mar 17 '13 at 01:32
  • @AndrewSpott: I think that is true. – Vaughn Cato Mar 17 '13 at 01:35