0

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;
        }
    }
}
4
  • 6
    "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." Are you not able to use std::array<T, N>::data()? Commented Mar 6, 2019 at 19:37
  • 4
    Why do you attempt to init integers with float literals? Commented Mar 6, 2019 at 19:37
  • 1
    You can't directly return C-style arrays from a function. Either use std::array or wrap the C-style array in a struct. Commented Mar 6, 2019 at 19:37
  • 1
    You can pass std::array to a C routine. Use std::array::data() or even &arr[0] would do (but the .data version is better) Commented Mar 6, 2019 at 19:40

2 Answers 2

3

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

11 Comments

sizeof(arr) isn't correct. the class could have padding. arr.size() or C++20's std::size(arr) would be better.
You are right. I already thought about that. But i will have to do the arr.data() everywhere afterward. But I would like to avoid that if possible. But I agreed with that solution.
@NathanOliver: As you're a big fish do feel empowered to change something that's so obviously wrong.
@NathanOliver: Except the OP has changed it back. Back in my box ;-) and an upvote for good feelings.
@NathanOliver C-style arrays often require you provide specific byte sizes, not the "element count" provided by std::array::size().
|
0

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);

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.