0

I've trimmed down the EXPECT_TRUE macro from gtest.h.

#include <type_traits>
#include <iostream>

class rai_class {
    public:
        static bool const value = true;
};

class AssertionResult {
 public:
  template <typename T>
  explicit AssertionResult(
      const T& success,
      typename std::enable_if<
          !std::is_convertible<T, AssertionResult>::value>::type*
          = nullptr)
      : success_(success) {}

  operator bool() const { return success_; }
 private:
  bool success_;
};

// Test type trait
bool test_rai_hash_implemented()
{
    return AssertionResult(rai_class::value);
    //return rai_class::value;
}

int main()
{
    std::cout << test_rai_hash_implemented() << "\n";
    return 0;
}

Without optimisations, it produces the link error "undefined reference to `rai_class::value'".

With -O2 it works ok. Any ideas what's going on?

Rai
  • 908
  • 7
  • 20
  • With the coliru link: http://coliru.stacked-crooked.com/a/d840e71525240865 – Rai Jan 31 '20 at 11:43
  • There is a workaround in `AssertionResult(rai_class::value == true)`, but it's a little unsatisfactory. – Rai Jan 31 '20 at 12:36

1 Answers1

0

rai_class::value is ODR-used (through const T& success), and so requires a definition.

bool const rai_class::value;

Demo

or use constexpr (which is implicitly inline since C++17)

class rai_class {
public:
    static bool constexpr value = true;
};

Demo

Jarod42
  • 173,454
  • 13
  • 146
  • 250
  • Thanks. `value` in our code was actually given the same assignment as the enum in this answer: https://stackoverflow.com/a/257382/1958315. Your answer motivates changing the definition to an `enum`, which works. – Rai Jan 31 '20 at 14:55