0

I have an image with int[Components] components per pixel.

I want get() return an int[Components] reference when Components != 1 and an int& when Components == 1.

pos is a pointer to raw image data.

I already read this StackOverflow question before ask, but I have no success.

The following code compiles ok, but returns garbage.

#include <iostream>

template<typename ComponentType, uint8_t Size>
struct A
{
    typedef typename std::conditional<Size == 1,
            ComponentType&, ComponentType(&)[Size]>::type SampleType;

    SampleType get()
    {
        if constexpr (Size == 1) return *pos;
        else return reinterpret_cast<SampleType>(pos);
    }
    void advance() { pos += Size; }

    ComponentType *pos;
};  

int main()
{
    int i[10] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    A<int, 2> a{i};

    std::cout << (size_t) &a << "\r\n";
    std::cout << (size_t) a.get() << "\r\n";
    std::cout << (size_t) a.pos << "\r\n";
    std::cout << (size_t) i << "\r\n";

    for(int c : a.get())
        std::cout << c << " ";
    a.get()[1] = 1000;
    return 0;
}

The code has the following output. Pointer values indicates that I totally screwed.

2293256
2293256
2293264
2293264
2293264 0

Can I ask what I was terribly wrong? How to fix this? Of-course get() can return a pointer if Components != 1 but I want the ability to use for( _ : _ )

Chameleon
  • 1,804
  • 2
  • 15
  • 21
  • I’m not nearly… something… enough to say that it’s safe, but I think `return *reinterpret_cast(pos)` with `SampleType& get()` and `SampleType` not being a reference is closer? – Ry- Sep 28 '19 at 22:57
  • (clang says dereferencing a pointer to `int[2]` `reinterpret_cast` from a pointer to `int` is still undefined behaviour, and I believe it.) – Ry- Sep 28 '19 at 23:00

2 Answers2

1

A span is probably good for this.

template<typename ComponentType, uint8_t Size>
struct A
{
    typedef typename std::conditional<Size == 1,
            ComponentType&, span<ComponentType, Size>>::type SampleType;

    SampleType get()
    {
        if constexpr (Size == 1) return *pos;
        else return span<ComponentType, Size>(pos, Size);
    }
    void advance() { pos += Size; }

    ComponentType *pos;
};
Ry-
  • 218,210
  • 55
  • 464
  • 476
0

Solution strictly on returning an array reference. Although span solution is very neat.

template<typename ComponentType, uint8_t Size>
struct A
{
    typedef typename std::conditional<Size == 1,
            ComponentType, ComponentType[Size]>::type SampleType;

    SampleType& get()
    {
        if constexpr (Size == 1) return *pos;
        else return *reinterpret_cast<SampleType*>(pos);
    }
    void advance() { pos += Size; }

    ComponentType *pos;
};  
Chameleon
  • 1,804
  • 2
  • 15
  • 21