簡體   English   中英

將cctype函數分配給std :: function,gcc編譯錯誤

[英]Assign cctype function to std::function, gcc compile error

嗨,我希望你喜歡這個問題。 我說的是包含文件cctype的函數iscntrlisprint等。 所有這些函數都采用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起)中很少有函數是所謂的可尋址函數 只能使用適當的參數調用所有其他參數,而不能使用其地址。

甚至在此之前,該標准還不能保證沒有重載,其效果幾乎相同。

你的情況是

即使僅直接包含第一個標頭,所有標准標頭也可能包括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.

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