I would like somebody to clarify in which cases it is safe to use a static constexpr as a default argument to a class's constructor. To weed out exactly what is going on, consider the following code:
#include <array> #include <iostream> struct Bar { using Option = size_t; using Options = std::array<Option, 0>; static constexpr Option default_option = 8080; static constexpr Options default_options{}; //template <typename OptionT = Options> Bar( Options options = default_options, Option option = default_option ){ std::cout << "Constructed with option " << option << std::endl; } }; int main() { Bar bar; } This code seems to compile, but does not link. Specifically, when compiling with GCC 6.3, I get
prog.cc:(.text+0x13): undefined reference to `Bar::default_options' collect2: error: ld returned 1 exit status However, if we comment out the offending line, then the code compiles, links, and runs correctly. So presumably there is no problem using a static constexpr size_t as a default argument:
#include <array> #include <iostream> struct Bar { using Option = size_t; using Options = std::array<Option, 0>; static constexpr Option default_option = 8080; static constexpr Options default_options{}; //template <typename OptionT = Options> Bar( //Options options = default_options, Option option = default_option ){ std::cout << "Constructed with option " << option << std::endl; } }; int main() { Bar bar; } Can somebody explain to me why the linkage works for a size_t, but not for an array of them?
I am aware that I could define the default options inline like this:
Bar( Options options = std::array<Option, 0>{}, Option option = default_option ){ std::cout << "Constructed with option " << option << std::endl; } I was just wondering if there was any other nicer fix so that the default options could easily be queried by anyone.