簡體   English   中英

包裝模板功能和

[英]wrapping template function and <unresolved overloaded function type

我的包裝功能有問題。

template <typename Iter, typename SomeFunction>                         
void wrap(Iter first, Iter last, SomeFunction someFunction)
{
  someFunction(first, last);
}

我想像這樣使用它:

template <typename Iter>
void fill5(Iter first, Iter last)
{
    fill(first, last, 5); 
}
int main()
{
    vector<int> v(100, -1);
    wrap(v.begin(), v.end(), fill5);

}

但我明白了

test.cpp: In function ‘int main()’:
test.cpp:16:40: error: no matching function for call to ‘wrap(std::vector<int>::iterator, std::vector<int>::iterator, <unresolved overloaded function type>)’
test.cpp:16:40: note: candidate is:
wrap.h:6:6: note: template<class Iter, class SomeFunction> void wrap(Iter, Iter, someFunction)

我知道如果我會這樣稱呼這個功能

wrap(v.begin(), v.end(), fill5< vector<int>::iterator> );

它會編譯。 但我是否總是要明確這樣做? 太糟糕了。 為什么編譯器無法推斷出將使用哪個函數? 是否有可能編寫wrap函數來獲取第一個參數?

在C ++ 03或C ++ 11中,你無能為力。

fill5是一個函數模板 ,你不能獲取函數模板的地址。 編譯器將函數模板視為無限重載集,並要求您明確指定要采用以下地址的實例:

wrap(v.begin(), v.end(), fill5<vector<int>::iterator>);
//                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

或者(正如我在原始帖子的評論中提到的,以及其他答案建議),您可以使用帶有模板化調用運算符的fill5函數來包裝fill5的調用。

但是,在C ++ 14中,我們可以做得更好:我們可以使用通用lambdas來簡化一些事情。 如果您定義此宏:

#define WRAP(f) \
    [&] (auto&&... args) -> decltype(auto) \
    { return f (std::forward<decltype(args)>(args)...); }

然后你可以寫:

int main()
{
    std::vector<int> v(100, -1);
    wrap(v.begin(), v.end(), WRAP(fill5));
}

這是一個實例

另一種方法是使用仿函數:

class fill5
{
public:
    template <typename Iter>
    void operator () (Iter first, Iter last) const
    {
        std::fill(first, last, 5); 
    }
};

int main( int, char ** )
{
    std::vector<int> v(100, -1);

    wrap(v.begin(), v.end(), fill5);
    return 0;
}

因為fill是一個模板函數,所以基本上存在無限數量的重載,編譯器不知道選擇哪一個。

如果你聲明你的第二個模板參數來描述一個帶有2個Iter類型參數的函數,那么它就可以推導出它。 以下示例有效,看起來就像您想要的那樣。 它並不像你的嘗試那樣通用。 它確保被調用的函數返回void並且需要2個Iter參數。

template <typename Iter >
void wrap( Iter first, Iter last, void(*someFunction)(Iter,Iter) )
{
someFunction( first, last );
}

template <typename Iter>
void fill5(Iter first, Iter last)
{
    fill(first, last, 5); 
}

int main( int, char ** )
{
std::vector<int> v(100, -1);
wrap(v.begin(), v.end(), fill5);

return( 0 );
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM