C ++:有没有办法在线定义静态数组?

时间:2010-02-05 15:19:57

标签: c++ templates

我想定义一个简单的模板函数,它接受运行时值并确定它是否是某些可能值的成员。

用法:

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;
}

这也使它更加灵活。

有人提供改进吗?更好的方法来定义“内联静态值集”

6 个答案:

答案 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;
}