Vuwox
Vuwox

Reputation: 2359

Avoid narrowing warning on c-style array creation

In c++11, the current behavior returns a warning:

int arr[3] = { 0.0f, 1.0f, 2.0f};

Based on the following post, I was able to create

template <class T, class ... Ts>
std::array<T, sizeof...( Ts )> make_non_narrowed_arr(Ts&& ... ts)
{
    return{ { static_cast<T>( ts )... } };
}

auto arr = make_not_narrowed_arr<int>(0.0f, 1.0f, 2.0f );

But I would like the return to be a classic c-array, but I was not able to achieve it. So far I tried those, but none are compiling.

template<class T, class ... Ts>
T[sizeof...( Ts )] make_non_narrowed_arr(Ts&& ... ts) {...};

template<class T, std::size_t N, class ... Ts>
T[N] make_non_narrowed_arr(Ts&& ... ts) {...};

template<class T, class ... Ts>
T* make_non_narrowed_arr(Ts&& ... ts) {...};

I want to do the following to have a warning free program, without suppressing them in compiler. So this post is not a solution for me either.

And I can't change to std::array for that specific usage since it need to be use afterward in a c routine that use T* only.

EDIT: Here a sample (not the exact code 100%) of what I have as code, and what I want to change.

The problem with the function is that based on image type and channel, I perform call to IPP routine, and I provide generic float* as input to the wrapper routine.

void threshold(Image img, Image dst, float* th)
{
    // Sanitty ckeck on image, and bla bla...

    // Perform the call to ipp
    IppStatus sts = (IppStatus)0;
    switch(img.nbChan)
    {
        case 1:
        {
            switch(img.type)
            {
                case BYTE:
                {
                    Ipp8u arr[1] = {Th[0] };
                    sts = ippiThreshold_GTVal_8u_C1R(img.data, img.pitch, dst.data, dst.pitch, arr);
                    break;
                }
                case FLOAT:
                {
                    Ipp32f arr[1] = {Th[0] };
                    sts = ippiThreshold_GTVal_32f_C1R(img.data, img.pitch, dst.data, dst.pitch, arr);
                    break;
                }
            }        
            break;
        }
        case 3:
        {
            switch(img.type)
            {
                case BYTE:
                {
                    Ipp8u arr[3] = {Th[0], Th[1], Th[2]};
                    sts = ippiThreshold_GTVal_8u_C3R(img.data, img.pitch, dst.data, dst.pitch, arr);
                    break;
                }
                case FLOAT:
                {
                    Ipp32f arr[3] = {Th[0], Th[1], Th[2]};
                    sts = ippiThreshold_GTVal_32f_C3R(img.data, img.pitch, dst.data, dst.pitch, arr);
                    break;
                }
            } 
            break;
        }
    }
}

Upvotes: 0

Views: 171

Answers (2)

Vuwox
Vuwox

Reputation: 2359

Finally, after all this discussion, I revisited my problem and tries to make something simple that fill my need, despite is not a super general function.

template<typename T, std::size_t N>
void no_narrow(float * const in, T(&out)[N])
{
    for ( int i = 0; i < N; i++ )
        out[i] = static_cast<T>( in[i] );
}

So that I call it:

Ipp8u arr[3];
no_narrow(th, arr);

Upvotes: 0

Xirema
Xirema

Reputation: 20396

Just use std::array. You assert that you're unable to do so as a result of needing to interface with C-style APIs, but that doesn't mean you need to use C-style arrays in your code.

//C Header
void do_something(void * arr, size_t size);

//C++ Code
auto arr = make_non_narrowed_array<int>(0.f, 1.f, 2.f);
//If size is meant to be the memory footprint
do_something(arr.data(), sizeof(arr));
//If size is meant to be the number of elements
do_something(arr.data(), arr.size());

No need to use a C-style array for this code.

If you're worried about excess boilerplate code, just write a wrapper.

template<typename T, size_t N> 
void cpp::do_something(std::array<T, N> const& arr) {
    do_something(arr.data(), arr.size() * sizeof(T));
}

Upvotes: 3

Related Questions