mardi 29 octobre 2019

Why does `constexpr` constant produce linker error? [duplicate]

Using gcc 9.2.1, I get a strange linker error with this code. When I compile with this line:

g++ -std=c++11 -Wall -Wextra -pedantic foo.cpp -o foo

I get this error:

/usr/bin/ld: /tmp/ccLjChns.o: in function `Foo::Foo()':
foo.cpp:(.text._ZN3FooC2Ev[_ZN3FooC5Ev]+0x11): undefined reference to `Foo::empty'
collect2: error: ld returned 1 exit status

If I change the contents of the constructor to board.fill('x');, however, everything works just fine.

I think this is because fill wants a reference instead of a value passed, but I'm not sure how to fix this while still using the named constant. Note that I'm using C++11 and not C++20, so I can't use the constexpr form of std::array::fill. I also wasn't able to figure out a way to use aggregate initialization or list initialization that uses both side and empty.

I know I could create a custom char class and assign a default initializer, but that seems inelegant and overly verbose.

foo.cpp

#include <iostream>
#include <algorithm>
#include <iterator>
#include <array>

class Foo {
public:
    Foo() { board.fill(empty); }
    friend std::ostream& operator<<(std::ostream& out, const Foo& foo);
private:
    static constexpr unsigned side{3};
    static constexpr char empty{'x'};
    std::array<char, side*side> board;
};

std::ostream& operator<<(std::ostream& out, const Foo& foo) {
    std::copy(std::begin(foo.board), std::end(foo.board), std::ostream_iterator<char>{out, ","});
    return out;
}

int main()
{
    Foo foo;
    std::cout << foo;
}

Aucun commentaire:

Enregistrer un commentaire