C++: существует ли способ определить статический встроенный массив?

Я хотел бы определить простую шаблонную функцию, которая принимает значение во время выполнения и определяет, является ли это член некоторого набора возможных значений.

Использование:

int x;  // <- pretend this came from elsewhere...
if (isoneof(x, {5,3,9,25}) ...

Что-то как:

template <typename T, size_t size>
bool isoneof(T value, T (&arr)[size])
{
    for (size_t i = 0; i < size; ++i)
        if (value == arr[i])
            return true;
    return false;
}

Я предполагаю, что это обречено на отказ, поскольку я не вижу, как можно создать статический встроенный массив.

Я могу использовать:

int kPossibilities[] = {5,3,9,25};
if (isoneodf(6, kPossibilities)) ...

С незначительным изменением к isoneof:

template <typename T1, typename T2, size_t size>
bool isoneof(T1 value, const T2 (&arr)[size])
{
    for (size_t i = 0; i < size; ++i)
        if (value == arr[i])
            return true;
    return false;
}

Который также делает это немного более гибким.

У кого-либо есть улучшение предложения? Лучший способ определить "набор статических встроенных значений"?

12
задан Mordachai 5 February 2010 в 15:19
поделиться

4 ответа

Если я правильно помню IsReusable указывает ASP.NET, что обработчик не должен быть уничтожен после обработки запроса и тот же экземпляр может быть использован для обработки последующих запросов. То есть один экземпляр объекта обработчика не обрабатывает несколько запросов одновременно.

-121--4407471-

Отказ от ответственности: Я понятия не имею, что авторы Scala думают об этом, я просто выражаю свое мнение как разработчик scala (и питона и рубина).

Пройдя через Scala API, вы не видите много способов сделать то же самое. Например, изменяемые и неизменяемые версии объектов имеют одинаковый интерфейс. Такие вещи дают Скале некоторую согласованность.

Будучи гибридным языком, обычно существует два способа решения проблемы: функциональный и процедурный путь (foreach vs for). Конечно, если бы вы хотели использовать процедурный способ, вы бы просто использовали Java.

Если вы посмотрите на функциональные языки, такие как Lisp и Haskell, обычно есть один способ сделать это для каждого подхода, который вы используете (так как вы можете решить проблему в рекурсивном или список понимания, например).

Наконец, я считаю, что любой код должен быть очевиден для чтения. И очевидно писать. Вы можете быть либо очень гибкими (perl/ruby) или строгими (python). Scala является гибким хорошо (подумайте синтаксис использования "". и скобки в вызовах метода, но вы можете сделать его настолько строгим, насколько вы хотите. Лично мне нравятся строгие вещи, поэтому я напишу свой собственный код, то, что я думаю, это очевидный способ.

-121--2602298-

Если вам нравятся такие вещи, то вы будете очень счастливым пользователем Boost.Assign .

Boost.Assign фактически доказывает, что такая семантика возможна, однако один взгляд на источник присвоения убедит вас, что вы не хотите делать это самостоятельно:)

Вы сможете создать что-то подобное, однако:

if (isoneof(x, list_of(2)(3)(5)(7)(11)) { ...

... минус в том, что вам придется использовать boost:: array в качестве параметра вместо встроенного массива (спасибо, Мануэль) - однако, это хороший момент, чтобы на самом деле начать использовать их: >

12
ответ дан 2 December 2019 в 07:21
поделиться

Это возможно в следующем стандарте C ++.

До тех пор вы можете обойти это, например, оператор перегрузки , для статического объекта, который запускает статический массив.

Примечание: эта реализация O (n ^ 2) и может быть оптимизирована - это просто для понимания.

using namespace std;

template< typename T, size_t N > 
struct CHead {
    T values[N];
    template< typename T > CHead<T,N+1> operator,( T t ) { 
      CHead<T,N+1> newhead;
      copy( values, values+N, newhead.values);
      newhead.values[N]=t;
      return newhead;
    }
    bool contains( T t ) const { 
       return find( values, values+N, t ) != values+N; 
    }
};

struct CHeadProto {
  template< typename T > 
  CHead<T,1> operator,( T t ) { 
     CHead<T,1> h = {t}; 
     return h; 
  }
} head;



int main()
{
  assert( (head, 1,2,3,4).contains(1) );
  return 0;
}
5
ответ дан 2 December 2019 в 07:21
поделиться

Для полноты я выложу решение, использующее Boost.MPL. Следующее работает, но я думаю, что решение Корнеля лучше.

#include <iostream>
#include <boost/mpl/for_each.hpp>
#include <boost/mpl/vector_c.hpp>

struct Contains
{
    Contains(int value, bool& result) : value(value), result(result)
    {
        result = false;
    }

    template< typename T > void operator()(T x)
    {
        result = result || (x == value);
    }

    int value;
    bool& result;
};


template <class IntList>
bool isoneof(int val)
{
    namespace mpl = boost::mpl;
    bool result;
    mpl::for_each<IntList>(Contains(val, result));
    return result;
}


int main()
{
    namespace mpl = boost::mpl;
    std::cout << isoneof< mpl::vector_c<int, 1,2,3,5,7,11> >(4) << "\n";
    std::cout << isoneof< mpl::vector_c<int, 1,2,3,5,7,11> >(5) << "\n";
}

Как видите, массив времени компиляции передается inline в качестве аргумента шаблона в isoneof.

2
ответ дан 2 December 2019 в 07:21
поделиться

Этот?

int ints[] = {2,3,5,7,11};
#define ARRAY_SIZE(Array) (sizeof(Array)/sizeof((Array)[0]))
#define INLIST(x,array) isoneof(x,array,ARRAY_SIZE(array))

ДОПОЛНЕНИЕ:

template <typename T>
bool isoneof(const T& x, T *array, int n)
{
        for(int i=0; i<n; ++i)
                if(x==array[i])
                        return true;
        return false;
}
1
ответ дан 2 December 2019 в 07:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: