欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

深入理解c++20 concepts

 更新時間:2023年06月25日 11:42:09   作者:程序員小x  
本文主要介紹了深入理解c++20 concepts,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

concepts在c++20中被引入,其作用是對模板參數(shù)進行約束,極大地增強了c++模板的功能。

在c++20之前,如果希望獲取類似的效果,使用起來并不方便。

沒有concept時,如何實現(xiàn)對模板參數(shù)進行約束?

static_assert

我們可以使用static_assert去對模板類型T進行約束。如下所示:

#include <type_traits>
#include <iostream>
template<class T>
void test(T a)
{
? ? static_assert(std::is_integral<T>());
? ? std::cout << "T is integral" << std::endl;
}
int main()
{
? ? test(10);
? ? test<double>(12.3);?
}

但是該種方法不太好,因為需要將static_assert嵌入到函數(shù)的內(nèi)部,這意味著即使類型不對,模板還是成功的匹配上了,只是在模板函數(shù)內(nèi)部展開時出現(xiàn)編譯錯誤。

SFINAE

SFINAE是Substitution Failure Is Not An Error的縮寫,翻譯過來的意思是替換失敗并不是一個錯誤。

SFINAE是模板元編程中常見的一種技巧,如果模板實例化后的某個模板函數(shù)(模板類)對該調(diào)用無效,那么將繼續(xù)尋找其他重載決議,而不是引發(fā)一個編譯錯誤。

因此一句話概括SFINAE,就是模板匹配過程中會嘗試各個重載模板,直到所有模板都匹配失敗,才會認為是真正的錯誤。

例如下面這個經(jīng)典的例子:

struct Test {
? ? ?typedef int foo;
};
template <typename T>
void f(typename T::foo) {} ?// Definition #1
template <typename T>
void f(T) {} ?// Definition #2
int main() {
? ? f<Test>(10); ?// Call #1.
? ? f<int>(10); ? // Call #2. Without error (even though there is no int::foo)
? ? ? ? ? ? ? ? // thanks to SFINAE.
}

f<Test>(10)最終將使用到第一個模板定義, 而f<int>(10)最終將使用到第二個模板定義。

SFINAE 原則最初是應用于上述的模板編譯過程。后來被C++開發(fā)者發(fā)現(xiàn)可以用于做編譯期的決策,配合sizeof可以進行一些判斷:類是否定義了某個內(nèi)嵌類型、類是否包含某個成員函數(shù)等。例如STL中迭代器中的has_iterator_category。

template <typename T>
struct has_iterator_category {
? ? struct two { char a; char b; };
? ? template <typename C>
? ? static two& test(typename C::iterator_category*);
? ? template <typename>
? ? static char& test(...);
? ? static const bool value = sizeof(test<T>(nullptr)) == sizeof(two);
};

enable_if

enable_if的出現(xiàn)使得SFINAE使用上更加方便,進一步擴展了上面has_xxx,is_xxx的作用。而enable_if實現(xiàn)上也是使用了SFINAE。

enable_if的定義簡單, 即當_Test是true時,將不會有type的類型定義,而當_Test是false時,將會有type的類型定義。

// STRUCT TEMPLATE enable_if
template <bool _Test, class _Ty = void>
struct enable_if {}; // no member "type" when !_Test
template <class _Ty>
struct enable_if<true, _Ty> { // type is _Ty for _Test
? ? using type = _Ty;
};

下面是利用enable_if去實現(xiàn)SFINAE的方式。

#include <type_traits>
#include <iostream>
template <typename T>
typename std::enable_if<std::is_integral<T>::value, T>::type?
test(T value)
{
? ? std::cout<<"T is intergal"<<std::endl;
? ? return value;
}
template <typename T>
typename std::enable_if<!std::is_integral<T>::value, T>::type?
test(T value)
{
? ? std::cout<<"T is not intergal"<<std::endl;
? ? return value;
}
int main()
{
? ? test(100);
? ? test('a');
? ? test(100.1);
}

可以看到SFINAE的主要實現(xiàn)了is_xxx和has_xxx的語義,但是其語法并不簡單,對使用者有較高要求,并且即便寫正確了,可讀性也相對較差。

有了concept之后如何使用?

聲明concept

聲明一個concept的語法如下所示:

template < template-parameter-list >
concept concept-name = constraint-expression;

例如,約束T是一個整形:

template <typename T>
concept integral = std::is_integral_v<T>;

也可以使用requires更加靈活地定義concept,例如下面的例子要求T類型擁有一個名字叫做print的方法,另外需要擁有一個toString方法,并且返回值是string類型。

template <typename T>
concept printable = requires(T t) {
    t.print(); //1
    {t.toString()} -> std::same_as<std::string>; //2
};

使用concept

使用concept有三種方式:

方法1:直接將concept嵌入模板的類型的尖括號<>內(nèi)

template<Arithmetic T> 
void f(T a){/*function definition*/};
we can enforce it just after template declaration using requires:

方法2:在模板聲明的下方使用requires關鍵字

template<class T> 
requires Arithmetic<T>
void f(T a)
{/*function definition*/};
or after the function declaration

方法3:使用后置形式,直接在函數(shù)聲明的后方使用requires關鍵字添加約束。

#include<concepts>
template<class T>
void f(T a) requires integral<T> // integral is in header <concepts>    
{/*function definition*/}; 

此外,concept還可以使用邏輯運算符 && 和 ||。例如:

template <class T>
concept Integral = std::is_integral<T>::value;
template <class T>
concept SignedIntegral = Integral<T> && std::is_signed<T>::value;
template <class T>
concept UnsignedIntegral = Integral<T> && !SignedIntegral<T>;

下面是兩個完整的例子來看看concepts是如何實現(xiàn)了is_xxx和has_xxx的功能。

第一個例子中test模板T只能是整形或者是double。實現(xiàn)了is_xxx。

#include <iostream>
template <class T>
concept Integral = std::is_integral<T>::value;
template <class T>
concept IsDouble = std::is_same<T, double>::value;
template<Integral T>
void test(T a)
{
? ? std::cout << "test(int) functin called" << std::endl;
}
template<IsDouble T>
void test(T a)
{
? ? std::cout << "test(double) functin called" << std::endl;
}
int main()
{
? ? test(100);
? ? test(10.0);
}

第二個例子中print函數(shù)要求t擁有print函數(shù)。實現(xiàn)了has_xxx。

#include <iostream>
template <typename T>
concept Has_print = requires(T t) {
? ? t.print(); //1
};
class HasPrint
{
public:
? ? void print(){};
};
class NoPrint
{
};
template<Has_print T>
void print(T t)
{
? ? t.print();
}
int main()
{
? ? HasPrint t;
? ? print(t);
? ? NoPrint t2;
? ? print(t2); //將報編譯錯誤
}

總結

c++20的concepts增強了模板對于參數(shù)類型約束的功能,語法簡單,可以提高代碼的可讀性。
如果你的項目不能使用較新的標準,那么還是要老老實實的使用SNINAE,enable_if那一套東西。

到此這篇關于深入理解c++20 concepts的文章就介紹到這了,更多相關c++20 concepts內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • VS+QT編譯環(huán)境中字符亂碼問題解決方法

    VS+QT編譯環(huán)境中字符亂碼問題解決方法

    編碼就是把?個字符編碼成二進制碼存起來的方式,而解碼就是把這個二進制碼按照原本編碼的規(guī)則還原成原來的字符,這篇文章主要介紹了VS+QT編譯環(huán)境中字符亂碼問題詳解,需要的朋友可以參考下
    2024-01-01
  • 淺析C++中的多態(tài)與文件操作

    淺析C++中的多態(tài)與文件操作

    多態(tài)是面向對象編程(OOP)的核心概念之一,它允許對象在相同操作下表現(xiàn)出不同的行為,本文主要為大家介紹了C++中多態(tài)與文件操作的相關知識,希望對大家有所幫助
    2024-04-04
  • 一文帶你學習C++中的派生機制

    一文帶你學習C++中的派生機制

    C++是一門面向對象的編程語言,其中的派生機制是其重要的面向對象特性之一。本文我們就來詳細地學習一下C++中的派生機制的相關知識吧
    2023-04-04
  • C++ Boost Parameter超詳細講解

    C++ Boost Parameter超詳細講解

    Boost是為C++語言標準庫提供擴展的一些C++程序庫的總稱。Boost庫是一個可移植、提供源代碼的C++庫,作為標準庫的后備,是C++標準化進程的開發(fā)引擎之一,是為C++語言標準庫提供擴展的一些C++程序庫的總稱
    2022-11-11
  • C++回溯算法中子集問題分析探討

    C++回溯算法中子集問題分析探討

    回溯法是一種選優(yōu)搜索法,按選優(yōu)條件向前搜索,以達到目標。但當探索到某一步時,發(fā)現(xiàn)原先選擇并不優(yōu)或達不到目標,就退回一步重新選擇,這種走不通就退回再走的技術為回溯法,而滿足回溯條件的某個狀態(tài)的點稱為回溯點
    2023-03-03
  • C++實現(xiàn)學生成績管理系統(tǒng)

    C++實現(xiàn)學生成績管理系統(tǒng)

    這篇文章主要為大家詳細介紹了C++實現(xiàn)學生成績管理系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-12-12
  • Window10下安裝VS2022社區(qū)版的實現(xiàn)步驟(圖文教程)

    Window10下安裝VS2022社區(qū)版的實現(xiàn)步驟(圖文教程)

    很多和同學們在接觸c語言的時候都是使用VS,本文主要介紹了Window10下如何安裝VS2022社區(qū)版的實現(xiàn)步驟,具有一定的參考價值,感興趣的可以了解一下
    2024-02-02
  • QT+Quick實現(xiàn)自定義組件的示例詳解

    QT+Quick實現(xiàn)自定義組件的示例詳解

    這篇文章主要為大家詳細介紹了如何利用QT+Quick實現(xiàn)自定義組件(按鈕、下拉菜單等),文中的示例代碼講解詳細,感興趣的小伙伴可以了解一下
    2022-11-11
  • C語言植物大戰(zhàn)數(shù)據(jù)結構堆排序圖文示例

    C語言植物大戰(zhàn)數(shù)據(jù)結構堆排序圖文示例

    這篇文章主要為大家介紹了C語言植物大戰(zhàn)數(shù)據(jù)結構堆排序的圖文示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-05-05
  • C++超詳細講解引用和指針

    C++超詳細講解引用和指針

    引用是C++一個很重要的特性,顧名思義是某一個變量或對象的別名,對引用的操作與對其所綁定的變量或對象的操作完全等價,這篇文章主要給大家總結介紹了C++中引用的相關知識點,需要的朋友可以參考下
    2022-06-06

最新評論