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( _ : _ )

2
  • I’m not nearly… something… enough to say that it’s safe, but I think return *reinterpret_cast<SampleType*>(pos) with SampleType& get() and SampleType not being a reference is closer? Commented Sep 28, 2019 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.) Commented Sep 28, 2019 at 23:00

2 Answers 2

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;
};
Sign up to request clarification or add additional context in comments.

2 Comments

I missed span. It is a very nice solution. But mingw64 gcc 8.1 does not support it yet.
@Chameleon: There’s a single-header implementation at github.com/tcbrindle/span.
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;
};  

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.