保护用户免于指定策略模板参数

时间:2011-08-02 03:54:53

标签: c++ templates design-patterns iterator istream-iterator

我正在设计一种istream_iterator(称之为my_istream_iterator),用于从输入流中提取单词。从迭代器中提取的单词将被处理的方式与单词在流中分隔的方式无关,但单词本身可以遵循许多格式中的一种。为了适应这种情况,我希望用户能够在使用输入流创建my_istream_iterator时指定策略类,而无需用户在迭代器的模板参数列表中指定策略类的类型。例如,如果我想以行主顺序输出CSV文件中的条目,我希望能够做到这样的事情:

std::ifstream is("words.csv");

// Assume that the_policy_class is used to read a special kind
// of CSV file that deviates from the standard specification.

// I don't want to have to specify the type of the policy class
// used by the iterator; how would I be able to do this? (The
// value_type of `mystream_iterator` is always char*).
my_istream_iterator begin = csv_begin<the_policy_class>(
    is, the_policy_class('\t', '\n', 1));

// Default constructor for end-of-stream iterator.
my_istream_iterator end;

std::ostream_iterator<char*> out(std::cout, ", ");

// Print the words, delimited by commas, to stdout.
std::copy(begin, end, out);

如果迭代器内部使用了策略类,那么在创建mystream_iterator时如何备用指定策略类类型的用户表单?这可能吗?

感谢您的帮助!


如果有帮助,my_istream_iterator类的定义可能如下所示:

template <typename Character, typename CharTraits = std::char_traits<Character>,
    typename Distance = std::ptrdiff_t>
class basic_my_istream_iterator : public std::iterator<std::input_iterator_tag,
    const Character*, Distance>
{
      /* ... */  
};

typedef basic_my_istream_iterator<char> my_istream_iterator;
typedef basic_my_istream_iterator<wchar_t> my_wistream_iterator;

2 个答案:

答案 0 :(得分:2)

对于您的任务,由于std::istream_iterator<T>使用T的{​​{1}},因此无需构建自己的istream迭代器。例如:

operator<<()

答案 1 :(得分:1)

如下所示:

class my_istream_policy_base {
  virtual ~my_istream_policy_base() = 0;
  virtual char* find_next_break(char*, size_t) = 0;
}

template<typename T>
my_istream_iterator csv_begin(std::ifstream is, T pol) {
  return my_istream_iterator(is, new T(pol));
}

然后确保每个策略都继承自my_istream_policy_wrapper_base,并为my_istream_iteratorifstream编写适当的构造函数。my_istream_policy_base*请注意,您需要将策略保留在std :: shared_ptr中,或者执行其他操作来管理其生命周期。

效率不高,但写作和使用相对容易。