Simpler way to set multiple array slots to one value

前端 未结 10 2220
我寻月下人不归
我寻月下人不归 2021-02-18 16:31

I\'m coding in C++, and I have the following code:

int array[30];
array[9] = 1;
array[5] = 1;
array[14] = 1;

array[8] = 2;
array[15] = 2;
array[23] = 2;
array[1         


        
相关标签:
10条回答
  • 2021-02-18 17:06

    I just had a play around for the sake of fun / experimentation (Note my concerns at the bottom of the answer):

    It's used like this:

    smartAssign(array)[0][8]       = 1;
    smartAssign(array)[1][4][2]    = 2;
    smartAssign(array)[3]          = 3;
    smartAssign(array)[5][9][6][7] = 4;
    

    Source code:

    #include <assert.h> //Needed to test variables
    #include <iostream>
    #include <cstddef>
    
    template <class ArrayPtr, class Value>
    class SmartAssign
    {
        ArrayPtr m_array;
    
    public:
        class Proxy
        {
            ArrayPtr m_array;
            size_t m_index;
            Proxy* m_prev;
    
            Proxy(ArrayPtr array, size_t index)
                : m_array(array)
                , m_index(index)
                , m_prev(nullptr)
            { }
    
            Proxy(Proxy* prev, size_t index)
                : m_array(prev->m_array)
                , m_index(index)
                , m_prev(prev)
            { }
    
            void assign(Value value)
            {
                m_array[m_index] = value;            
                for (auto prev = m_prev; prev; prev = prev->m_prev) {
                    m_array[prev->m_index] = value;
                }
            }
    
        public:
            void operator=(Value value)
            {
                assign(value);
            }
    
            Proxy operator[](size_t index)
            {
              return Proxy{this, index};
            }
    
            friend class SmartAssign;
        };
    
        SmartAssign(ArrayPtr array)
            : m_array(array)
        {
        }
    
    
        Proxy operator[](size_t index)
        {
            return Proxy{m_array, index};
        }
    };
    
    template <class T>
    SmartAssign<T*, T> smartAssign(T* array)
    {
        return SmartAssign<T*, T>(array);
    }
    
    int main()
    {
        int array[10];
    
        smartAssign(array)[0][8]       = 1;
        smartAssign(array)[1][4][2]    = 2;
        smartAssign(array)[3]          = 3;
        smartAssign(array)[5][9][6][7] = 4;
    
        for (auto i : array) {
            std::cout << i << "\n";
        }
    
        //Now to test the variables
        assert(array[0] == 1 && array[8] == 1);
        assert(array[1] == 2 && array[4] == 2 && array[2] == 2);
        assert(array[3] == 3);
        assert(array[5] == 4 && array[9] == 4 && array[6] == 4 && array[7] == 4);
    }
    

    Let me know what you think, I don't typically write much code like this, I'm sure someone will point out some problems somewhere ;)

    I'm not a 100% certain of the lifetime of the proxy objects.

    0 讨论(0)
  • 2021-02-18 17:06

    Compilers which still doesn't support variadic template argument and universal initialization list, it can be a pain to realize, that some of the posted solution will not work

    As it seems, OP only intends to work with arrays of numbers, valarray with variable arguments can actually solve this problem quite easily.

    #include <valarray>     
    #include <cstdarg>
    #include <iostream>
    #include <algorithm>
    #include <iterator>
    template <std::size_t size >
    std::valarray<std::size_t>  selection( ... )
    {
        va_list arguments; 
        std::valarray<std::size_t> sel(size);   
        //Skip the first element
        va_start ( arguments, size );
        va_arg ( arguments, int );
        for(auto &elem : sel)
            elem = va_arg ( arguments, int );
        va_end ( arguments );
        return sel;
    
    }
    int main ()
    {
        //Create an array of 30 integers
        std::valarray<int> array(30);
        //The first argument is the count of indexes
        //followed by the indexes of the array to initialize
        array[selection<3>(9,5,14)] = 1;
        array[selection<4>(8,15,13, 12)] = 2;
        std::copy(std::begin(array), std::end(array),
                  std::ostream_iterator<int>(std::cout, " "));
        return 0;
    }
    
    0 讨论(0)
  • 2021-02-18 17:07

    I remember, for static initialization exist syntax like:

    int array[30] = {
      [9] = 1, [8] = 2
    }
    

    And so on. This works in gcc, about another compilers - I do not know.

    0 讨论(0)
  • 2021-02-18 17:12

    The best you can do if your indexes are unrelated is "chaining" the assignments:

    array[9] = array[5] = array[14] = 1;
    

    However if you have some way to compute your indexes in a deterministic way you could use a loop:

    for (size_t i = 0; i < 3; ++i)
        array[transform_into_index(i)] = 1;
    

    This last example also obviously applies if you have some container where your indexes are stored. So you could well do something like this:

    const std::vector<size_t> indexes = { 9, 5, 14 };
    for (auto i: indexes)
        array[i] = 1;
    
    0 讨论(0)
提交回复
热议问题