2017-10-05 58 views
3

我需要将表示向量01​​s的字符串转换为相应的向量。将默认值作为忽略它们的参数传递

我的问题是,我想通过一个简单的参数:转换器功能。这里的split

template <class T> 
auto split(const std::string &s, const std::function<T(const std::string&)> &convert, char sep = ',') -> std::vector<T> 
{ 
    std::stringstream ss(s); 
    std::vector<T> result; 

    while (ss.good()) 
    { 
     std::string substr; 
     std::getline(ss, substr, sep); 
     if (!substr.empty()) 
      result.push_back(convert(substr)); 
    } 
    return result; 
}; 

它无法通过标准功能时,如因std::stoistd::stoi默认参数为它的签名是int stoi(const string& __str, size_t* __idx = 0, int __base = 10);编译:

auto q = split<int>(subs, std::stoi); 

error: no matching function for call to 'split' 
      auto q = split<int>(subs, std::stoi); 
        ^~~~~~~~~~ 

很显然我可以欺骗编译器使用lambda函数:

auto q = split<std::size_t>(subs, [](const std::string &s){ return std::stoul(s); }); 

是否有一个元编程技巧,允许我索姆ehow 忽略的默认参数?

+0

默认参数是什么意思?你明确指定你想要'分割'。 – nwp

+0

我的意思是'std :: stoi'实际上有默认参数:签名是'int stoi(常量字符串&__str,size_t * __idx = 0,int __base = 10);'。我希望忽略该默认签名。 – senseiwa

+0

如果你可以避免使用std :: function,它会让你的生活更轻松。 (模板化的函数参数会更好。) – alfC

回答

4
#define RETURNS(...) \ 
    noexcept(noexcept(__VA_ARGS__)) \ 
    -> decltype(__VA_ARGS__) \ 
    { return __VA_ARGS__; } 

#define OVERLOADS_OF(...) \ 
    [](auto&&...args) \ 
    RETURNS(__VA_ARGS__(decltype(args)(args)...) 

这个宏让你把一个函数的名称,并生成一个包含它的重载拉姆达。

auto q = split<std::size_t>(subs, OVERLOADS_OF(std::stroul)); 

这是很好和简洁。

默认参数只能通过调用()来调用函数的实际名称,“将名称移动到不同的上下文中”的唯一方法是将其作为文本填充到lambda表达式中。

顺便说一下,@ barry有一个建议,用代替上面的RETURNS(X)代表lambdas。我不知道目前维护的提案取代OVERLOADS_OF宏(曾经有一段时间)。

可能反射提议将允许您访问函数名称的默认参数和重载集,然后幻想元编程会让您在没有宏的情况下生成OVERLOADS_OF

5

编辑:这实际上并没有帮助在这种情况下。我要离开它,因为它在其他一些情况下很有用,例如,如果您的函数返回了可兑换为T的东西,但它没有解决与stoi有关的任何问题。


不明确指定函数的类型。假设convert是任何类型;如果您尝试传递某些无法在std::string上调用的东西,或者不会返回可转换为T的东西,那么您会收到错误消息。没有理由限制这种类型,除非你明确地具有它需要的特定类型的原因,在这种情况下你不需要。

因此,你可以声明功能

template <class T, class F> 
auto split(const std::string &s, const F&& convert, char sep = ',') -> std::vector<T> 
+0

在通话点传递'strtoi'时,这不起作用。 – Yakk

+0

@Yakk呃,是的,超载。我不认为SFINAE可以真正处理这个问题,所以我不知道是否可以在没有宏的调用站点透明地工作,但我可能是错的。 –

+0

甚至没有重载。对于零重载,传入的函数指针或引用(并且它必须解析为要传入的对象)不会带有默认参数。所以在通话时它不会起作用。 – Yakk