代码之家  ›  专栏  ›  技术社区  ›  Mordachai

C++是否有一种方法来定义一个静态数组?

  •  11
  • Mordachai  · 技术社区  · 14 年前

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

    用途:

    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)) ...
    

    稍微改一下 同一 :

    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 回复  |  直到 6 年前
        1
  •  12
  •   Kornel Kisielewicz    14 年前

    如果你喜欢这样的东西,那么你将是一个非常快乐的用户 Boost.Assign .

    assign实际上证明了这种语义 有可能,但是只要看一下分配源,就会发现您不想自己这样做:)

    但是,您将能够创建如下内容:

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

    …缺点是你必须使用 boost::array 作为参数而不是内置数组(谢谢,Manuel)——不过,这是实际开始使用它们的好时机:>

        2
  •  5
  •   xtofl Adam Rosenfield    14 年前

    在下一个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;
    }
    
        3
  •  2
  •   Emile Cormier    14 年前

    为了完整起见,我将发布一个使用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";
    }
    

    如您所见,编译时数组作为模板参数内联传递给 isoneof .

        4
  •  1
  •   Notinlist    14 年前

    这一个?

    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;
    }
    
        5
  •  1
  •   Laurent LA RIZZA    11 年前

    使用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; });
    }
    
        6
  •  0
  •   Mordachai    6 年前

    只是FYI——我用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;
    }