c++ - remix - smart contracts ethereum
Una forma más sencilla de establecer múltiples ranuras de matriz en un valor (10)
Acabo de jugar por diversión / experimentación (tenga en cuenta mis preocupaciones al final de la respuesta):
Se usa así:
smartAssign(array)[0][8] = 1;
smartAssign(array)[1][4][2] = 2;
smartAssign(array)[3] = 3;
smartAssign(array)[5][9][6][7] = 4;
Código fuente:
#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);
}
Déjame saber lo que piensas, normalmente no escribo mucho código como este, estoy seguro de que alguien señalará algunos problemas en alguna parte;)
No estoy 100% seguro de la vida útil de los objetos proxy.
Estoy codificando en C++ , y tengo el siguiente código:
int array[30];
array[9] = 1;
array[5] = 1;
array[14] = 1;
array[8] = 2;
array[15] = 2;
array[23] = 2;
array[12] = 2;
//...
¿Hay una manera de inicializar la matriz similar a la siguiente?
int array[30];
array[9,5,14] = 1;
array[8,15,23,12] = 2;
//...
Nota: En el código real, puede haber hasta 30 ranuras que deben configurarse en un valor.
El compilador / ensamblador desenrollará cualquier truco de fantasía que haga exactamente lo que tiene. ¿Estás haciendo esto por razones de legibilidad? Si su matriz ya es init, puede hacer:
array[8] = array[15] = array[23] = array[12] = 2;
Pero subrayo mi punto anterior; Se transformará en exactamente lo que tienes.
Esta función ayudará a que sea menos doloroso.
void initialize(int * arr, std::initializer_list<std::size_t> list, int value) {
for (auto i : list) {
arr[i] = value;
}
}
Llámalo así.
initialize(array,{9,5,14},2);
Lo mejor que puede hacer si sus índices no están relacionados es "encadenar" las asignaciones:
array[9] = array[5] = array[14] = 1;
Sin embargo, si tiene alguna forma de calcular sus índices de una manera determinista, podría usar un bucle:
for (size_t i = 0; i < 3; ++i)
array[transform_into_index(i)] = 1;
Este último ejemplo también se aplica obviamente si tiene algún contenedor donde se almacenan sus índices. Así que bien podrías hacer algo como esto:
const std::vector<size_t> indexes = { 9, 5, 14 };
for (auto i: indexes)
array[i] = 1;
Recuerdo, para la inicialización estática existen sintaxis como:
int array[30] = {
[9] = 1, [8] = 2
}
Y así. Esto funciona en gcc, sobre otros compiladores - No lo sé.
Solo por el gusto de hacerlo, creé un enfoque algo diferente que necesita un poco de infraestructura que permita la inicialización así:
double array[40] = {};
"9 5 14"_idx(array) = 1;
"8 15 23 12"_idx(array) = 2;
Si los dígitos deben estar separados por comas, se necesita un pequeño cambio. En cualquier caso, aquí está el código completo:
#include <algorithm>
#include <iostream>
#include <sstream>
#include <iterator>
template <int Size, typename T = int>
class assign
{
int d_indices[Size];
int* d_end;
T* d_array;
void operator=(assign const&) = delete;
public:
assign(char const* base, std::size_t n)
: d_end(std::copy(std::istream_iterator<int>(
std::istringstream(std::string(base, n)) >> std::skipws),
std::istream_iterator<int>(), this->d_indices))
, d_array()
{
}
assign(assign<Size>* as, T* a)
: d_end(std::copy(as->begin(), as->end(), this->d_indices))
, d_array(a) {
}
assign(assign const& o)
: d_end(std::copy(o.begin(), o.end(), this->d_indices))
, d_array(o.d_array)
{
}
int const* begin() const { return this->d_indices; }
int const* end() const { return this->d_end; }
template <typename A>
assign<Size, A> operator()(A* array) {
return assign<Size, A>(this, array);
}
void operator=(T const& value) {
for (auto it(this->begin()), end(this->end()); it != end; ++it) {
d_array[*it] = value;
}
}
};
assign<30> operator""_idx(char const* base, std::size_t n)
{
return assign<30>(base, n);
}
int main()
{
double array[40] = {};
"1 3 5"_idx(array) = 17;
"4 18 7"_idx(array) = 19;
std::copy(std::begin(array), std::end(array),
std::ostream_iterator<double>(std::cout, " "));
std::cout << "/n";
}
Una variante de la respuesta de aaronman:
template <typename T>
void initialize(T array[], const T& value)
{
}
template <size_t index, size_t... indices, typename T>
void initialize(T array[], const T& value)
{
array[index] = value;
initialize<indices...>(array, value);
}
int main()
{
int array[10];
initialize<0,3,6>(array, 99);
std::cout << array[0] << " " << array[3] << " " << array[6] << std::endl;
}
Ejemplo: haga clic aquí
Utilizar operador de sobrecarga <<.
#include <iostream>
#include <iomanip>
#include <cmath>
// value and indexes wrapper
template< typename T, std::size_t ... Ints> struct _s{ T value; };
//deduced value type
template< std::size_t ... Ints, typename T>
constexpr inline _s<T, Ints... > _ ( T const& v )noexcept { return {v}; }
// stored array reference
template< typename T, std::size_t N>
struct _ref
{
using array_ref = T (&)[N];
array_ref ref;
};
//join _s and _ref with << operator.
template<
template< typename , std::size_t ... > class IC,
typename U, std::size_t N, std::size_t ... indexes
>
constexpr _ref<U,N> operator << (_ref<U,N> r, IC<U, indexes...> ic ) noexcept
{
using list = bool[];
return ( (void)list{ false, ( (void)(r.ref[indexes] = ic.value), false) ... }) , r ;
//return r;
}
//helper function, for creating _ref<T,N> from array.
template< typename T, std::size_t N>
constexpr inline _ref<T,N> _i(T (&array)[N] ) noexcept { return {array}; }
int main()
{
int a[15] = {0};
_i(a) << _<0,3,4,5>(7) << _<8,9, 14>( 6 ) ;
for(auto x : a)std::cout << x << " " ;
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
//result: 7 0 0 7 7 7 0 0 6 6 0 0 0 0 6
double b[101]{0};
_i(b) << _<0,10,20,30,40,50,60,70,80,90>(3.14)
<< _<11,21,22,23,24,25>(2.71)
<< _<5,15,25,45,95>(1.414) ;
}
Compilers que aún no admiten el argumento de plantilla variada y la lista de inicialización universal , puede ser una molestia darse cuenta de que parte de la solución publicada no funcionará
Como parece, la OP solo intenta trabajar con matrices de números, una valarray con argumentos variables puede resolver este problema con bastante facilidad.
#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;
}
struct _i_t
{
int * array;
struct s
{
int* array;
std::initializer_list<int> l;
s const& operator = (int value) const noexcept
{
for(auto i : l )
array[i] = value;
return *this;
}
};
s operator []( std::initializer_list<int> i ) const noexcept
{
return s{array, i};
}
};
template< std::size_t N>
constexpr _i_t _i( int(&array)[N]) noexcept { return {array}; }
int main()
{
int a[15] = {0};
_i(a)[{1,3,5,7,9}] = 7;
for(auto x : a)std::cout << x << '' '';
}