2017-10-05 65 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