4

I have found questions that are almost exactly as mine but I have 1 extra requirement - I need something that I can use as a default argument.

I'm writing a header only template library and I have a code like this:

#include <chrono>

template <typename T>
class Foo
{
public:
    using Duration = std::chrono::duration<float>;
    static constexpr Duration DefaultDuration{1.0f};
    Foo(Duration duration = DefaultDuration)
        : duration{duration}
    {
    }
private:
    Duration duration;
};

int main(int argc, char* argv[])
{
    Foo<int> foo;
}

As you can see, I can't use a function call because it wouldn't work as a default argument, right? Is there a solution?

UpAndAdam
  • 4,515
  • 3
  • 28
  • 46
  • *"As you can see, I can't use a function call because it wouldn't work as a default argument, right?"* Well, what happened when you tried? (Hint: You're wrong.) – Baum mit Augen Oct 09 '16 at 23:13
  • I get "undefined reference". G++ 6.1.1 –  Oct 09 '16 at 23:16
  • So you got something wrong while implementing the underlying concept. [mcve] for that please. – Baum mit Augen Oct 09 '16 at 23:17
  • 1
    I was getting something similar but with source tucked into a separate .h and .cpp file. The header file had the default value just about the same as your example, but in the cpp file it needed the following `constexpr Duration Foo::DefaultDuration;`. This was being built with clang with warnings as errors. – jxramos Jan 09 '20 at 21:37

1 Answers1

4

The issue here does not appear to be the default parameter, but the initialization. By switching to the uniform initialization syntax, and explicitly declared the static class member, this compiles without issues, with gcc 6.2.1:

#include <chrono>

template <typename T>
class Foo
{
public:

    static constexpr std::chrono::duration<float> DefaultDuration{1.0f};

    Foo(std::chrono::duration<float> duration = DefaultDuration);
};

template<typename T>
constexpr std::chrono::duration<float> Foo<T>::DefaultDuration;

Foo<int> f;

int main()
{
    return 0;
}

gcc 6.2.1 actually lets you skate by without explicitly defining the static const member, but this is technically required, as explained here.

Morwenn
  • 21,684
  • 12
  • 93
  • 152
Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148