English 中文(简体)
大约单程模板
原标题:About variadic templates

目前,Im正在经历新的C++0x variadic模板,而且很疲软,尽管我对成员即时过程有疑问。

举例来说,Im试图效仿强硬体,选择随机有效的大体(用于单位测试)。


#include<vector>
#include<iostream>

using namespace std;

template<unsigned... values> struct sp_enum;

/*
 this is the solution I found, declaring a globar var
 vector<unsigned> _data;

 and it work just fine

*/

template<> struct sp_enum<>{
  static const unsigned _count  = 0;
  static vector<unsigned> _data;
};

vector<unsigned> sp_enum<>::_data;

template<unsigned T, unsigned... values>
struct sp_enum<T, values...> : private sp_enum<values...>{
  static const unsigned _count = sp_enum<values...>::_count+1;
  static vector<unsigned> _data;

  sp_enum(                       ) : sp_enum<values...>(values...) {_data.push_back(T);}
  sp_enum(unsigned v             )                                 {_data.push_back(v);}
  sp_enum(unsigned v, unsigned...) : sp_enum<values...>(values...) {_data.push_back(v);}
};

template<unsigned T, unsigned... values> vector<unsigned> sp_enum<T, values...>::_data;

int main(){
  enum class t:unsigned{Default = 5, t1, t2};
  sp_enum<t::Default, t::t1, t::t2> test;
  cout <<test._count << endl << test._data.size() << endl;  
  for(auto i= test._data.rbegin();i != test._data.rend();++i){cout<< *i<< ":";}
}



加入该法典的Im结果是:

3
1
5:

难道有人会告诉我我我我,我在这里说什么?

P-3:使用4.4.3


我重新拟订该守则,使其更加通用,并尽可能减少核心编码(@Matthieu M.)。 但我要解释一下,我为什么要这样做。

我已经看到,许多发展者在我的法典中接受了新的C++0x标准,我对此表示高兴。 但是,在试图撰写测试单位时,我有很强的字面。

问题在于,你不能产生一种随意的强体(我知道,你可以,但希望以更合法的方式这样做)。 因此,现在,根据这一法典,我可以使用理论模板和理论宏观(即旧的 d脏宏观)来宣布和随机选择一个高度分类和范围大体。

这部法律是:


#include<vector>
#include<iostream>

#include <boost/preprocessor/array/elem.hpp>
#include <boost/preprocessor/repetition/repeat.hpp>
#include <boost/preprocessor/repetition/repeat_from_to.hpp>

using namespace std;

template<typename T, T... values> class sp_enum;

template<typename T> class sp_enum<T>{
  protected: static const unsigned _count  = 0;
};

template<typename T, T head, T... values>
class sp_enum<T, head, values...> : public sp_enum<T, values...>{
protected:
  static const unsigned _count = sp_enum<T, values...>::_count+1;
  static vector<T> _data;

public:
  sp_enum(         ) : sp_enum<T, values...>(values...) {_data.push_back(head);for(auto i= sp_enum<T, values...>::_data.begin();i != sp_enum<T, values...>::_data.end();++i){_data.push_back(*i);}}
  sp_enum(T v      )                                    {_data.push_back(v   );}
  sp_enum(T v, T...) : sp_enum<T, values...>(values...) {_data.push_back(v   );for(auto i= sp_enum<T, values...>::_data.begin();i != sp_enum<T, values...>::_data.end();++i){_data.push_back(*i);}}

  vector<T> data()  const { return _data  ;}
  unsigned  count() const { return _count ;}

  static T randomEnum() { srand (time(NULL));return _data[rand()%_count];}

};

template<typename T, T head, T... values> vector<T> sp_enum<T, head, values...>::_data;

#define PP_NARG(...)  PP_NARG_(__VA_ARGS__,PP_RSEQ_N())
#define PP_NARG_(...) PP_ARG_N(__VA_ARGS__)

#define PP_ARG_N( 
         _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, 
        _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, 
        _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, 
        _61,_62,_63,N,...) N

#define PP_RSEQ_N() 
        63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40, 
        39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16, 
        15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0

#define FOREACH_ARRAY( ... )  (PP_NARG(__VA_ARGS__) , ( __VA_ARGS__ ) )
#define FOREACH( Name, A, ... )     BOOST_PP_REPEAT_FROM_TO(1, PP_NARG(Name, __VA_ARGS__), A, FOREACH_ARRAY(Name, __VA_ARGS__) )
#define DECORATION(z,n,data)  ,BOOST_PP_ARRAY_ELEM( 0, data ) :: BOOST_PP_ARRAY_ELEM( n, data ) 

#define SP_ENUM(enumName, ...)                                
  enum class _##enumName : unsigned { Default, __VA_ARGS__ }; 
  typedef sp_enum<_##enumName FOREACH( _##enumName, DECORATION, Default, __VA_ARGS__) > enumName;

SP_ENUM( xx, test1, test2, test3 )

int main(){
  xx test;
  cout <<test.count() << endl << test.data().size() << endl; 
  auto dt = test.data();
  for(auto i = dt.rbegin(); i != dt.rend();++i){ cout<< (unsigned)*i << ":" ; }
  cout << "random strongly typed enum : " << (unsigned) test.randomEnum() << endl;
}

我现在说的是,购买力平价的宏观局限性(我没有找到任何其他办法计算论点数目)。

我将高兴地接受任何观点或训.,以加强这一作用。

最佳回答

http://www.ohchr.org。

问题回答

由于这个问题已经变成了我。

难道你们会这样做吗? 职业介绍我不知道会增加学前图书馆,但似乎没有这样做。 唯一的问题是,是否算是编纂时常数?

#include<vector>
#include<iostream>
#include <cstdlib>

#define DECLARE_ENUM(enum_name, ...) 
enum class enum_name##_ : unsigned { __VA_ARGS__}; 
class enum_name { 
public: 
     static enum_name##_ random() { return static_cast<enum_name##_>(values[rand() % values.size()]); } 
     static unsigned count() { return values.size(); } 
     static std::vector<unsigned> data() { return values; } 
private: 
     enum : unsigned {__VA_ARGS__}; 
     static std::vector<unsigned> values; 
}; 
std::vector<unsigned> enum_name::values{__VA_ARGS__};

DECLARE_ENUM( xx, test1, test2, test3 )

int main(){
  xx test;
  std::cout <<test.count() << std::endl << test.data().size() << std::endl;
  auto dt = test.data();
  for(auto i = dt.rbegin(); i != dt.rend();++i){ std::cout<< (unsigned)*i << ":" ; }
  xx_ random_value = test.random();
  std::cout << "random strongly typed enum : " << (unsigned) random_value << std::endl;
}

诚然,设计可以做得更好,我对“虚构”概念毫不犹豫(如果你不要求连续的价值观,就会打破任何方向)。


另一种情况是,如果这只是支持连续的价值观,首先就没有病媒的理由。 只储存第一种(如果不是总价值)和最后价值,其他一切都可以计算。 数据方法可回归一系列的升值代码<>,标明_iterator。

或仅专门确定相应的海峡类别:

#include<iostream>
#include <cstdlib>

namespace detail {
template <unsigned ...values>
struct last;

template <unsigned N, unsigned ...values>
struct last<N, values...>
{
    static const unsigned value = last<values...>::value;
};

template <unsigned N>
struct last<N>
{
    static const unsigned value = N;
};

template <unsigned N, unsigned ...>
struct first
{
    static const unsigned value = N;
};
}
template <class T>
struct enum_traits;

#define DECLARE_ENUM(enum_name, ...) 
enum class enum_name : unsigned { __VA_ARGS__}; 
template <> struct enum_traits<enum_name> { 
private: enum : unsigned { __VA_ARGS__ }; 
public: 
     static const unsigned first = detail::first< __VA_ARGS__>::value; 
     static const unsigned last =  detail::last< __VA_ARGS__>::value; 
     static const unsigned count = last - first + 1; 
};

template <class T>
T random_enum_value()
{
    return static_cast<T>(rand() % enum_traits<T>::count + enum_traits<T>::first);
}

DECLARE_ENUM( xx, test1, test2, test3 )

int main(){
    std::cout << enum_traits<xx>::first <<     << enum_traits<xx>::last <<     << enum_traits<xx>::count <<  
 ;
    std::cout << (unsigned) random_enum_value<xx>() <<  
 ;
}

由于Pavel,我描述了这一问题。

这就是解决办法。


#include<vector>
#include<iostream>

using namespace std;

template<unsigned... values> struct sp_enum;

template<> struct sp_enum<>{
  static const unsigned _count  = 0;
  static vector<unsigned> _data;
};

vector<unsigned> sp_enum<>::_data;

template<unsigned T, unsigned... values>
struct sp_enum<T, values...> : private sp_enum<values...>{
  static const unsigned _count = sp_enum<values...>::_count+1;
  static vector<unsigned> _data;

  sp_enum(                       ) : sp_enum<values...>(values...) {_data.push_back(T);for(auto i= sp_enum<values...>::_data.begin();i != sp_enum<values...>::_data.end();++i){_data.push_back(*i);}}
  sp_enum(unsigned v             )                                 {_data.push_back(v);}
  sp_enum(unsigned v, unsigned...) : sp_enum<values...>(values...) {_data.push_back(v);for(auto i= sp_enum<values...>::_data.begin();i != sp_enum<values...>::_data.end();++i){_data.push_back(*i);}}

};

template<unsigned T, unsigned... values> vector<unsigned> sp_enum<T, values...>::_data;

int main(){
  enum class t:unsigned{Default = 5, t1, t2};
  sp_enum<t::Default, t::t1, t::t2> test;
  cout <<test._count << endl << test._data.size() << endl;  
  for(auto i= test._data.rbegin();i != test._data.rend();++i){cout<< *i<< ":";}
}

总而言之,这里的主要问题是,你将需要每 en一个例的<条码>查询器(斜线,斜线?)。

如果你使用2个论坛,你就不行。

因此,合乎逻辑的做法是:

template <class Enum>
struct sp_enum_vector { static std::vector<unsigned> _data; };

之后,将贵重类改为:

template <class Enum, unsigned... values>
struct sp_enum;

为了根据我们所谈论的大概来区别这一类别。

下一个问题: 如何从<条码>到<条码>>>>>上获取<条码>。 : :p





相关问题
Undefined reference

I m getting this linker error. I know a way around it, but it s bugging me because another part of the project s linking fine and it s designed almost identically. First, I have namespace LCD. Then I ...

C++ Equivalent of Tidy

Is there an equivalent to tidy for HTML code for C++? I have searched on the internet, but I find nothing but C++ wrappers for tidy, etc... I think the keyword tidy is what has me hung up. I am ...

Template Classes in C++ ... a required skill set?

I m new to C++ and am wondering how much time I should invest in learning how to implement template classes. Are they widely used in industry, or is this something I should move through quickly?

Print possible strings created from a Number

Given a 10 digit Telephone Number, we have to print all possible strings created from that. The mapping of the numbers is the one as exactly on a phone s keypad. i.e. for 1,0-> No Letter for 2->...

typedef ing STL wstring

Why is it when i do the following i get errors when relating to with wchar_t? namespace Foo { typedef std::wstring String; } Now i declare all my strings as Foo::String through out the program, ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

Window iconification status via Xlib

Is it possible to check with the means of pure X11/Xlib only whether the given window is iconified/minimized, and, if it is, how?

热门标签