0

EDIT: I was able fully minimize this question, thanks for feedbacks.

Now, i am working on a vector class(vector it is term from mathematics). This class has template for dimension and elements type. I am needing to define reference fields: X,Y, the syntax must do not require call brackets(v.X() - incorrect solution). My implementation for this:

#include <array>

template <typename Ty, size_t Size>
struct vector {
    std::array<Ty, Size> data;
    Ty& x{ this->data[0] };
    Ty& y{ this->data[1] };
};

constexpr vector<int, 2> const_context() {
    vector<int, 2> v1{ 1,2 };
    v1.data[0] = 1;
    return v1;
}

int main() {
    constexpr auto res = const_context();
}

If we comment x and y fields compile it is successful.

My instruments: Visual studio 2017 and C++ 17. The solution must be portable and do not depend on compiler.

PavelDev
  • 579
  • 4
  • 12
  • 2
    what is the error? what is the meaning of "does not work" ? – 463035818_is_not_an_ai Sep 16 '19 at 13:29
  • To the best of my knowledge, this is not feasible. What is the rationale for such stringent syntax restrictions? – L. F. Sep 16 '19 at 13:35
  • Cannot reproduce with g++ and clang++ – max66 Sep 16 '19 at 13:39
  • Updated, please see – PavelDev Sep 16 '19 at 13:55
  • 1
    Create one block of code I can copy paste and see exactly what you are seeing. – bolov Sep 16 '19 at 14:04
  • and your whole problem can be reduces to just 5 lines of code: this is a proper mcve: https://godbolt.org/z/zgEp0L The rest of what you show is just a distraction. – bolov Sep 16 '19 at 14:10
  • 1
    How about reverse dependency between x, y, z and `operator[]`: `template class impl { public: std::array data; T& operator[](std::size_t i) { return data[i]; };` And specialization: `template class impl { public: T x; T y; T& operator[](std::size_t i) { assert(i == 0 || i == 1); return i == 0 ? x : y; };` – Jarod42 Sep 16 '19 at 14:24

1 Answers1

1

Your problem can be reduced to this:

#include <array>

struct X
{
    constexpr X() = default;

    std::array<int, 2> data{};

    int& x { this->data[0]};
};


int main()
{
    constexpr auto res = X{};
}
<source>:14:20: error: constexpr variable 'res' must be initialized by a constant expression

    constexpr auto res = X{};

                   ^     ~~~

<source>:14:20: note: reference to subobject of 'res' is not a constant expression

<source>:14:20: note: declared here

The issue is that a constexpr reference can be bound only to objects with static storage duration (which this is not). See how to initialize a constexpr reference

So afaik it is not possible without making it a method (the x() syntax).

bolov
  • 72,283
  • 15
  • 145
  • 224