Я хотел бы определить простую шаблонную функцию, которая принимает значение во время выполнения и определяет, является ли это член некоторого набора возможных значений.
Использование:
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;
}
Который также делает это немного более гибким.
У кого-либо есть улучшение предложения? Лучший способ определить "набор статических встроенных значений"?
Если я правильно помню 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
в качестве параметра вместо встроенного массива (спасибо, Мануэль) - однако, это хороший момент, чтобы на самом деле начать использовать их: >
Это возможно в следующем стандарте 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;
}
Для полноты я выложу решение, использующее 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
.
Этот?
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;
}