Skip to content

搞英语 → 看世界

翻译英文优质信息和名人推特

Menu
  • 首页
  • 作者列表
  • 独立博客
  • 专业媒体
  • 名人推特
  • 邮件列表
  • 关于本站
Menu

使用“概念”在 C++ 中定义接口 (C++20)

Posted on 2023-04-19

肖像2018facebook.jpg

在较早的博客文章中,我展示了 Go 编程语言允许您在定义接口后编写通用函数。 Java 有一个非常相似的同名概念(接口)。我给出了以下示例:

类型IntIterable接口{  
   
    下一个( )布尔  
   
    下一个( ) uint32  
   
    重置( )  
   
}  
   
  
   
func Count ( i IntIterable ) ( count int ) {  
   
    计数= 0  
   
    我。重置( )  
   
    对于我。下一个( ) {  
   
        我。下一个( )  
   
        计数+ +  
   
    }  
   
    返回  
   
}  
   
  
   

从这段代码中,您所要做的就是提供一个支持该接口的类型(具有具有正确签名的方法 HasNext、Next 和 Reset),然后您就可以使用函数 Count。

C++呢?在传统的 C++ 中,您可以像这样编写一个 Count 模板:

 template < class T > size_t count ( T & t ) {  
   
  吨。重置( ) ;  
   
  size_t计数= 0 ;  
   
  while ( t . has_next ( ) ) {  
   
    吨。下一个( ) ;  
   
    计数+ + ;  
   
  }  
   
  返回计数;  
   
}  
   
  
   

这在适度使用时很好,但如果我是一名程序员并且我需要使用我不熟悉的模板函数,我可能必须阅读代码以找出我的类型需要实现什么才能与函数模板兼容.当然,它也限制了我用来编程的工具:它们对我将在 count 函数中实际使用的类型了解不多。

值得庆幸的是,C++ 现在具有相当于 Go 或 Java 接口的功能,它被称为概念(它需要支持 C++20 的最新编译器)。你会这样实现它……

模板<类型名T >  
   
概念 is_iterable = requires ( T v ) {  
   
                        {诉。 has_next ( ) } - > std :: convertible_to < bool > ;  
   
                        {诉。 next ( ) } - > std :: same_as < uint32_t > ;  
   
                        {诉。重置( ) } ;  
   
                      } ;  
   
  
   
template < is_iterable T > size_t count ( T & t ) {  
   
  吨。重置( ) ;  
   
  size_t计数= 0 ;  
   
  while ( t . has_next ( ) ) {  
   
    吨。下一个( ) ;  
   
    计数+ + ;  
   
  }  
   
  返回计数;  
   
}  
   
  
   

它甚至比等效的 Go 更好,因为正如我的示例所示,我不必严格要求has_next函数返回布尔值,我可以只要求它返回可以转换为布尔值的东西。在这个特定的示例中,我要求next方法返回一个特定类型 ( uint32_t ),但我可能需要一个整数 ( std::is_integral<T>::value ) 或一个数字 ( std:: is_arithmetic<T>::value )。

在 Go 中,我发现使用接口并不是免费的:它会使代码变慢。在 C++ 中,如果您实现以下类型并对其调用计数,您会发现优化编译器能够弄清楚它们需要返回内部向量的大小。换句话说:概念/模板的使用没有运行时成本。但是,您需要预先支付更长的编译时间。

结构iterable_array {  
   
    std :: vector <uint32_t>数组{ } ; _  
   
    size_t索引= 0 ;  
   
    void reset ( ) {索引= 0 ; }  
   
    bool has_next ( ) {返回索引<数组。尺寸( ) ; }  
   
    uint32_t next ( ) {索引+ + ;返回数组[索引- 1 ] ; }  
   
} ;  
   
  
   
size_t f ( iterable_array & a ) {  
   
    返回计数(一) ;  
   
}  
   
  
   

在 C++ 中,您甚至可以通过强制编译时计算使运行时成本绝对为零。诀窍是确保您的类型可以实例化为编译时常量,然后将其传递给计数函数。它现在可以与最近的 GCC 一起使用,但最终应该会得到广泛支持。在下面的代码中,函数只返回整数 10。

模板< is_iterable T >  
   
constexpr size_t count ( T & & t ) {  
   
    返回计数( t ) ;  
   
}  
   
  
   
结构iterable_array {  
   
    constexpr iterable_array ( size_t s ) :数组( s ) { }  
   
    std :: vector <uint32_t>数组{ } ; _  
   
    size_t索引= 0 ;  
   
    constexpr void reset ( ) { index = 0 ; }  
   
    constexpr bool has_next ( ) {返回索引<数组。尺寸( ) ; }  
   
    constexpr uint32_t next ( ) {索引+ + ;返回数组[索引- 1 ] ; }  
   
} ;  
   
  
   
  
   
consteval size_t f ( ) {  
   
    返回计数( iterable_array ( 10 ) ) ;  
   
}  
   
  
   
  
   

如果愿意,您可以检查我的源代码。

那么概念有什么用呢?我认为这主要是关于记录您的代码。例如,在 simdjson 库中,我们有get<T>()类型的模板方法,其中T是几种选择类型之一( int64_t 、 double 、 std::string_view等)。一些用户总是希望有一些神奇的东西,只是做get<mytypefromanotherlibrary>()希望 simdjson 会以某种方式有足够的过载。然后他们会收到一条令人讨厌的错误消息。通过使用概念,我们可能会限制这些编程错误。事实上,IDE 和 C++ 编辑器可能会立即捕捉到它。

原文: https://lemire.me/blog/2023/04/18/defining-interfaces-in-c-with-concepts-c20/

本站文章系自动翻译,站长会周期检查,如果有不当内容,请点此留言,非常感谢。
  • Abhinav
  • Abigail Pain
  • Adam Fortuna
  • Alberto Gallego
  • Alex Wlchan
  • Answer.AI
  • Arne Bahlo
  • Ben Carlson
  • Ben Kuhn
  • Bert Hubert
  • Bits about Money
  • Brian Krebs
  • ByteByteGo
  • Chip Huyen
  • Chips and Cheese
  • Christopher Butler
  • Colin Percival
  • Cool Infographics
  • Dan Sinker
  • David Walsh
  • Dmitry Dolzhenko
  • Dustin Curtis
  • eighty twenty
  • Elad Gil
  • Ellie Huxtable
  • Ethan Marcotte
  • Exponential View
  • FAIL Blog
  • Founder Weekly
  • Geoffrey Huntley
  • Geoffrey Litt
  • Greg Mankiw
  • Henrique Dias
  • Hypercritical
  • IEEE Spectrum
  • Investment Talk
  • Jaz
  • Jeff Geerling
  • Jonas Hietala
  • Josh Comeau
  • Lenny Rachitsky
  • Liz Danzico
  • Lou Plummer
  • Luke Wroblewski
  • Matt Baer
  • Matt Stoller
  • Matthias Endler
  • Mert Bulan
  • Mostly metrics
  • News Letter
  • NextDraft
  • Non_Interactive
  • Not Boring
  • One Useful Thing
  • Phil Eaton
  • Product Market Fit
  • Readwise
  • ReedyBear
  • Robert Heaton
  • Rohit Patel
  • Ruben Schade
  • Sage Economics
  • Sam Altman
  • Sam Rose
  • selfh.st
  • Shtetl-Optimized
  • Simon schreibt
  • Slashdot
  • Small Good Things
  • Steve Blank
  • Taylor Troesh
  • Telegram Blog
  • The Macro Compass
  • The Pomp Letter
  • thesephist
  • Thinking Deep & Wide
  • Tim Kellogg
  • Understanding AI
  • Wes Kao
  • 英文媒体
  • 英文推特
  • 英文独立博客
©2025 搞英语 → 看世界 | Design: Newspaperly WordPress Theme