[英]Assign cctype function to std::function, gcc compile error
嗨,我希望你喜歡這個問題。 我說的是包含文件cctype
的函數iscntrl
, isprint
等。 所有這些函數都采用int
並返回int
。
以下代碼示例在Wandbox中將編譯器設置為clang時運行良好。 但是在我的mingw-w64上,gcc8.1確實產生了編譯錯誤。 我嘗試了C ++ 14和C ++ 17。
#include <cstddef>
#include <cstdio>
#include <cstdint>
#include <string>
#include <tuple>
#include <functional>
#include <array>
#include <cctype>
//#include <ctype.h>
namespace abc
{
int two_times( int a )
{
printf( "two_times being called\n" );
return 2*a;
}
int three_times( int a )
{
printf( "three_times being called\n" );
return 3*a;
}
}
int main()
{
typedef std::tuple< std::string, std::function<int(int)> > item_t;
std::array< item_t, 3 > array{
std::make_tuple( "three_times", abc::three_times ),
std::make_tuple( "two_times", abc::two_times ),
std::make_tuple( "iscntrl", std::iscntrl ) };
int i = 2;
for( const item_t& item : array )
{
printf( "operation: %s\n", std::get<0>(item).c_str() );
int val = std::get<1>(item)( i );
printf( "val: %d\n", val );
putchar( '\n' );
}
getchar();
return 0;
}
如您所見,我將循環需要的所有相關內容放入數組中。 包括分配給cctype函數的函數對象。
這里的功能two_times和three_times表明我的其余設計都很好。 如果我只是使用這些功能,它將起作用。 但是在我眼里, std::iscntrl
只是另一個具有int
作為參數並返回int
函數。 但顯然不是,因為它會產生以下編譯錯誤:
error: too many arguments to function 'constexpr std::tuple<typename std::__decay_and_strip<_Elements>::__type ...> std::make_tuple(_Elements&& ...) [with _Elements = {}]'
std::make_tuple( "iscntrl", std::iscntrl ) };
哦,是的,如果您將包含文件替換為#include <ctype.h>
並刪除了iscntrl
前面的std::
名稱空間標簽,它突然也會起作用。 但這不是一個好習慣。 但是也許它告訴你一些事情。
使它變得更加簡單,都無法正常工作:
std::function<int(int)> f;
f = abc::two_times;
printf( “result: %d\n“, f( 4 ) ); // so far fine
f = std::iscntrl;
然后在最后一行:
error: no match for 'operator=' (operand types are 'std::function<int(int)>' and '<unresolved overloaded function type>')
f = std::iscntrl;
我有事嗎 用gcc進行編譯的簡單解決方案是什么?
標准庫(自C ++ 20起)中很少有函數是所謂的可尋址函數 。 只能使用適當的參數調用所有其他參數,而不能使用其地址。
甚至在此之前,該標准還不能保證沒有重載,其效果幾乎相同。
你的情況是
int iscntrl( int ch );
在<cctype>
和 template< class charT > bool iscntrl( charT ch, const locale& loc );
在<locale>
。 即使僅直接包含第一個標頭,所有標准標頭也可能包括C和采用的標頭之外的其他任何標頭,因此它們可能都可用。
當您傳遞給模板參數時,編譯器無法明確說明您要重載的是哪個。
您應該做的是根據需要傳遞lambda轉發。 另外,您可以使用它來將參數強制設置為unsigned char
的適當范圍,從而避免未定義的行為。
錯誤中將std::iscntrl
稱為<unresolved overloaded function type>
無法<unresolved overloaded function type>
,因為在C ++中,此函數確實已重載。 <cctype>
標頭中有一個int iscntrl( int )
重載,而<locale>
有一個bool iscntrl( charT ch, const locale& loc )
重載。 像這樣傳遞時,編譯器不知道選擇哪個函數。
要解決此問題並仍使用C ++版本,必須傳遞一個從內部調用iscntrl
的函數:
std::make_tuple( "iscntrl", [](int c) { return std::iscntrl(c); } );
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.