如何用pre-c 0x(VS2008)实现“Variadic Template”?
我使用的是Visual Studio 2008,我想实现没有变量参数列表的字符串格式化函数.
如何用pre-c 0x(VS2008)实现“Variadic Template”? 有没有任何图书馆实现这样的提升? 还是另一种方式来实现呢? 这是我的示例代码. bool VarPrint(std::ostringstream& out,const std::string& s) { std::string::size_type offset = 0; if((offset = s.find("%")) != std::string::npos) { if(!(offset != s.size() - 1 && s[offset + 1] == '%')) { ASSERT(!"Missing Arguments!"); return false; } } out << s; return true; } template<typename T,typename... Args> bool VarPrint(std::ostringstream& out,const std::string& s,const T& value,const Args&... args) { std::string::size_type prev_offset = 0; std::string::size_type curr_offset = 0; while((curr_offset = s.find("%",prev_offset)) != std::string::npos) { out << s.substr(prev_offset,curr_offset); if(!(curr_offset != s.size() - 1 && s[curr_offset + 1] == '%')) { out << value; if(curr_offset + 2 < s.length()) return VarPrint(out,s.substr(curr_offset + 2),args...); return true; } prev_offset = curr_offset + 2; if(prev_offset >= s.length) break; } ASSERT(!"Extra Argument Provided!"); return false; } 解决方法
在C 03,你有不同的可能性:
>为0-N参数生成重载(例如使用Boost.Preprocessor) 第一个选项是有点棘手,我觉得,因为并不是每个人都可以很容易的理解宏,所以我只会保留它的短期解决方案,如果你计划迁移到C 0x很快. 第三个选项可能会提供一个很好的自定义触摸(使用许多语言的%符号进行格式化),但这也意味着需要记住这个特定的“可变”功能如何每次都工作. 我的个人喜好是cons方法,因为它解决了这两个问题: >定义只涉及模板,所以它比1更可读和维护. 例如,这里是如何工作的: 这个例子包括: #include <cassert> #include <iostream> #include <string> 对于附加值的结果类型的帮助器(它可能会更有效的前置,但这意味着以相反的顺序传递参数是反直觉的): template <typename T,typename Next> struct Cons; struct ConsEmpty; template <typename Cons,typename U> struct cons_result; template <typename U> struct cons_result<ConsEmpty,U> { typedef Cons<U,ConsEmpty> type; }; template <typename T,typename U> struct cons_result<Cons<T,ConsEmpty>,U> { typedef Cons<T,Cons<U,ConsEmpty> > type; }; template <typename T,typename Next,Next>,typename cons_result<Next,U>::type> type; }; 缺点模板本身,用一个魔术运算符()来附加值.请注意,它会创建一个不同类型的新项目: template <typename T,typename Next> struct Cons { Cons(T t,Next n): value(t),next(n) {} T value; Next next; template <typename U> typename cons_result<Cons,U>::type operator()(U u) { typedef typename cons_result<Cons,U>::type Result; return Result(value,next(u)); } }; struct ConsEmpty { template <typename U> Cons<U,ConsEmpty> operator()(U u) { return Cons<U,ConsEmpty>(u,ConsEmpty()); } }; template <typename T> Cons<T,ConsEmpty> cons(T t) { return Cons<T,ConsEmpty>(t,ConsEmpty()); } 重读了VarPrint: bool VarPrint(std::ostream& out,ConsEmpty) { std::string::size_type offset = 0; if((offset = s.find("%")) != std::string::npos) { if(offset == s.size() - 1 || s[offset + 1] != '%') { assert(0 && "Missing Arguments!"); return false; } } out << s; return true; } template<typename T,typename Next> bool VarPrint(std::ostream& out,std::string const& s,Cons<T,Next> const& cons) { std::string::size_type prev_offset = 0,curr_offset = 0; while((curr_offset = s.find("%",prev_offset)) != std::string::npos) { out << s.substr(prev_offset,curr_offset); if(curr_offset == s.size() - 1 || s[curr_offset + 1] != '%') { out << cons.value; if(curr_offset + 2 < s.length()) return VarPrint(out,cons.next); return true; } prev_offset = curr_offset + 2; if(prev_offset >= s.length()) break; } assert(0 && "Extra Argument Provided!"); return false; } 和演示 int main() { VarPrint(std::cout,"integer %in",cons(1)); VarPrint(std::cout,"mix of %i and %sn",cons(2)("foo")); } 您可以查看ideone的输出: integer 1 mix of 2 and foo (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |