C++ c++;同一功能模板的多个接口

C++ c++;同一功能模板的多个接口,c++,c++11,overloading,C++,C++11,Overloading,我有几种方法可以处理utf8编码的字符串,这些字符串通常保存在std::string中 在同样的情况下,虽然我只是对数据使用const char*,或者数据是更大字符串的一部分,但我不想创建子字符串 所有功能归结为一种通用方法,即: void foo(int a, int b, const char* beginStr, const char* endStr); 现在,如果我想避免一些丑陋,我会创造 void foo(int a, int b, const char* beginStr, co

我有几种方法可以处理utf8编码的字符串,这些字符串通常保存在std::string中

在同样的情况下,虽然我只是对数据使用const char*,或者数据是更大字符串的一部分,但我不想创建子字符串

所有功能归结为一种通用方法,即:

void foo(int a, int b, const char* beginStr, const char* endStr);
现在,如果我想避免一些丑陋,我会创造

void foo(int a, int b, const char* beginStr, const char* endStr);
void foo(int a, int b, const char* str);
void foo(int a, int b, const std::string% str);
在某些情况下,甚至:

void foo(int a, int b, const std::string::const_iterator& beginStr
                       const std::string::const_iterator& endStr);
这似乎还可以,但正如我提到的,我有几种方法,维护所有这些口味真的很烦人


我所看到的是一些魔法,可以消除每个接口相乘的需要。c++11的一些特性是否可以帮助解决这个问题,而不会影响性能—使它不那么健谈

如注释中所述,作为
基本字符串视图的包装可以解决部分问题。
可变模板可以解决其他部分(不要明确使用
basic\u string\u view
):

void foo_impl(int a、int b、const basic_string_view&str);//真正的实施
模板
void foo(int a、int b、Ts&…args){
foo_impl(a,b,基本字符串视图{std::forward(args…});
}

如注释中所述,作为
基本字符串视图的包装可以解决部分问题。
可变模板可以解决其他部分(不要明确使用
basic\u string\u view
):

void foo_impl(int a、int b、const basic_string_view&str);//真正的实施
模板
void foo(int a、int b、Ts&…args){
foo_impl(a,b,基本字符串视图{std::forward(args…});
}
(删除了我之前的两个答案,希望第三次是魅力。)

这只是Jarod42的解决方案,但不依赖于
basic\u string\u视图

struct dispatcher {
  dispatcher(const char* begin, const char* end) : begin(begin), end(end) {}
  dispatcher(const char* str) : begin(str), end(str+strlen(str)) {}
  dispatcher(const std::string& str) : begin(&*(str.begin())), end(&*(str.end())) {}
  const char* begin;
  const char* end;
};

struct main_class {
  void foo(int a, int b, const char* begin, const char* end) {
    // implementation here
  }

  template<typename... Ts>
    void foo(int a, int b, Ts&&... args) {
      dispatcher d(std::forward<Ts>(args)...);
      foo(a, b, d.begin, d.end);
    }
};
struct调度程序{
调度程序(常量字符*开始,常量字符*结束):开始(开始),结束(结束){
调度程序(constchar*str):开始(str),结束(str+strlen(str)){
调度程序(const std::string&str):开始(&*(str.begin())),结束(&*(str.end()){}
常量字符*开始;
常量字符*结束;
};
结构主类{
void foo(整数a、整数b、常量字符*开始、常量字符*结束){
//在这里实现
}
模板
void foo(int a、int b、Ts&…args){
调度程序d(std::forward(args)…);
foo(a,b,d.begin,d.end);
}
};
(删除了我之前的两个答案,希望第三次是魅力。)

这只是Jarod42的解决方案,但不依赖于
basic\u string\u视图

struct dispatcher {
  dispatcher(const char* begin, const char* end) : begin(begin), end(end) {}
  dispatcher(const char* str) : begin(str), end(str+strlen(str)) {}
  dispatcher(const std::string& str) : begin(&*(str.begin())), end(&*(str.end())) {}
  const char* begin;
  const char* end;
};

struct main_class {
  void foo(int a, int b, const char* begin, const char* end) {
    // implementation here
  }

  template<typename... Ts>
    void foo(int a, int b, Ts&&... args) {
      dispatcher d(std::forward<Ts>(args)...);
      foo(a, b, d.begin, d.end);
    }
};
struct调度程序{
调度程序(常量字符*开始,常量字符*结束):开始(开始),结束(结束){
调度程序(constchar*str):开始(str),结束(str+strlen(str)){
调度程序(const std::string&str):开始(&*(str.begin())),结束(&*(str.end()){}
常量字符*开始;
常量字符*结束;
};
结构主类{
void foo(整数a、整数b、常量字符*开始、常量字符*结束){
//在这里实现
}
模板
void foo(int a、int b、Ts&…args){
调度程序d(std::forward(args)…);
foo(a,b,d.begin,d.end);
}
};

为什么有些方法有两个const char*,而另一些方法有一个?当你传递一个范围时,有两个句柄,一个是当你只知道开始的时候,它是以零结尾的。@Amit我可能更喜欢在宏上手动维护它们,但是当你提到它时,即使使用宏也似乎不那么容易。在C++11中不是这样,但推出后会很好。或者你可以使用实验性的实现。经验法则是,大多数你重复做的事情都有一些小的变化(例如函数名),你应该能够用宏来做。但这并不是说所有的事情都可以也应该这样做。为什么有些方法有两个const char*,而另一些方法有一个呢?当你通过一个范围时,有两个句柄,其中一个是当你只知道开始的时候,它是零终止的。@Amit我可能更喜欢通过宏手动维护它们,但现在当你提到它时,即使使用宏也似乎不太容易。在C++11中不是这样,但在推出后会很好。或者你可以使用实验性的实现。经验法则是,大多数你重复做的事情都有一些小的变化(例如函数名),你应该能够用宏来做。但这并不是说一切都可以也应该这样做。