我想定义一个简单的模板函数,它接受运行时值并确定它是否是某些可能值的成员。
用法:
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;
}
这也使它更加灵活。
有人提供改进吗?更好的方法来定义“内联静态值集”?
答案 0 :(得分:12)
如果你喜欢这样的话,那么你将是Boost.Assign的一个非常开心的用户。
Boost.Assign实际上证明了这种语义 是可能的,但是看一下assign的来源会说服你不要自己这样做:)
你可以创建这样的东西:
if (isoneof(x, list_of(2)(3)(5)(7)(11)) { ...
...缺点是你必须使用boost::array
作为参数而不是内置数组(感谢Manuel) - 然而,这是真正开始使用它们的好时机:&gt ;
答案 1 :(得分:5)
可以在下一个C ++标准中使用。
到目前为止,您可以通过以下方式解决问题:重载operator,
以获取启动静态数组的静态对象。
注意:这个实现是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;
}
答案 2 :(得分:2)
为了完整起见,我将发布一个使用Boost.MPL的解决方案。以下是有效的,但我认为Kornel的解决方案是最好的。
#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";
}
如您所见,编译时数组作为模板参数内联传递给isoneof
。
答案 3 :(得分:1)
这一个?
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;
}
答案 4 :(得分:1)
使用C ++ 11,这将写成:
template <typename T>
bool isoneof(T value, std::initializer_list<T> arr)
{
using namespace std;
return any_of(begin(arr), end(arr), [&](const T& x) { return x == value; });
}
答案 5 :(得分:0)
仅供参考 - 我现在使用vararg模板和初始化程序列表解决了我的特殊问题,因为我可以访问C ++ 14:
template <typename T, typename U>
bool isoneof(T v, U v1) { return v == v1; }
template <typename T, typename U, typename... Args>
bool isoneof(T v, U v1, Args ... others) { return isoneof(v, v1) || isoneof(v, others...); }
template <typename T, typename U>
bool isoneof(T value, std::initializer_list<U> values)
{
for (const auto & e : values)
if (value == e)
return true;
return false;
}