2

I am trying to write a template like this.

template <char c,typename Options, 
   basic_string<class,class,class> Options::* member> 
   struct option_string;

However I keep getting a compilation error. I would like to know how to write a template that takes three options: a char, any class and a pointer to a member of that class which must be a basic_string specialization. I want to avoid writing a template for each specialization of basic_string.

My goal is to created a generic command line option library. The following is how I would like to use it.

class Options : public Command_Line_Options_Parser<Options> {
public:
  int integer = 0;
  float real_number = 0.0;
  bool boolean = false;
  bool make_true = false;
  bool make_false = true;
  std::string string;
  typedef Options O;
  typedef Command_Line_Options<
            option_int<'i',&O::integer>,
            option_float<'f',&O::real_number>,
            option_bool<'b',&O::boolean>,
            option_true<'t',&O::make_true>,
            option_false<'t',&O::make_true>,
            option_string<'s',&O::string>
           >
  option_list;
};

int main(int argc,char**argv ) {

  Options options;

  options.parse(argc,argv);
  std::cout << "integer : " << options.integer <<endl;
  std::cout << "real_number : " << options.real_number <<endl;
  std::cout << "boolean : " << options.boolean <<endl;
  std::cout << "make_true : " << options.make_true <<endl;
  std::cout << "make_false : " << options.make_false <<endl;
  std::cout << "string : " << options.string <<endl;
};

I would prefer for option_string to accept all specializations of basic_string instead of just std::string.

4

1 に答える 1

6

リターンタイプを直接指定する必要はありません。そしてその場合、なぜbasic_stringクラスに直接迷惑をかけるのですか?取るだけtypename Stringで完了します:

template<char C, class Options, class String, String Options::* Member>
struct option_string;

Stringそれでも、それが本当に専門分野であることを確認したい場合はbasic_string、この小さなヘルパーとstatic_assertそれを使用してください。

#include <type_traits>
#include <string>

template<class T>
struct is_basic_string : std::false_type{};

template<class Ch, class Tr, class Al>
struct is_basic_string<std::basic_string<Ch,Tr,Al>> : std::true_type{};

// in 'option_string'
static_assert(is_basic_string<String>::value,
    "Data member must be a 'basic_string' specialization.");

メンバーポインタをテンプレート引数として渡す必要はないように思われるので、コンストラクタに渡すことをお勧めします。

template<char C, class Option, class String>
struct option_string{
  static_assert(is_basic_string<String>::value,
      "Data member must be a 'basic_string' specialization.");
  typedef String Option::*member_type;

  option_string(member_type m, ...) : member(m), ... { ... }
private:
  member_type member;
};

template<char C, class Option, class String>
option_string<C, Option, String> make_option_string(String Option::*member, ...){
  return {member, ...};
}

// in code:
auto os = make_option_string<'H'>(&some_type::a_string_member);
于 2012-09-24T19:05:45.413 に答える