mercredi 27 mars 2019

Linkage issues when using a static constexpr as default constructor argument

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.

Aucun commentaire:

Enregistrer un commentaire