簡體   English   中英

如何限制模板中的類型名

[英]How to restrict typenames in template

具有可以接受4種不同類型的功能。 它們的實現非常相似。

template< typename T >
void foo( std::string &&name, T value ){
    //...
}

typename T必須是 4 種預定義類型之一。 其他類型名是不可接受的,應在編譯時加以限制。
可以用 C++ 編寫嗎?

我能想到至少三種方式,從頭到尾。

第一:

namespace internal {
template< typename T >
void foo_impl( std::string &&name, T value ) {
    // actual implementation here
}
}

void foo(std::string &&name, SpecialType1 value ) {
    internal::foo_impl(std::forward<std::string>(name), value);
}
void foo(std::string &&name, SpecialType2 value ) {
    internal::foo_impl(std::forward<std::string>(name), value);
}

第二:

template< typename T >
typename std::enable_if<std::is_same<T, SpecialType1>::value ||
                        std::is_same<T, SpecialType2>::value >::type
foo( std::string &&name, T value ){
    //implementation here
}

第三:

template< typename T >
void foo(std::string &&name, T value){
    static_assert(std::is_same<T, SpecialType1>::value ||
                  std::is_same<T, SpecialType2>::value,
    "wrong template argument");
    //implementation here
}

演示

我見過人們做的一件事是使用std::enable_if 我不確切知道你的4種類型是什么,所以這是一個有兩種類型intfloat的例子。

using myType = std::enable_if<
std::is_same<int, T>::value ||
std::is_same<float, T>::value, T >::type;

只有當T完全是intfloat myType存在。 希望有所幫助!

<type_traits>允許您將邏輯推廣到類模板中。 這是如何工作的我們采取模板參數TTs參數包,我們開始檢查T是否與類型列表的Head相同。 如果找到匹配,我們繼承std::true_type ,我們就完成了。 如果沒有找到匹配,我們彈出頭部並以Ts尾部遞歸地實例化相同的模板。 最終,如果根本找不到匹配項,參數包大小將降至零,編譯器將實例化從std::false_type繼承的基本模板類。 請查看此視頻,以便更好地閱讀Walter E. Brown先生的部門解釋。

template<class T, class...> struct is_any_of: std::false_type{};
template<class T, class Head, class... Tail> 
struct is_any_of<T, Head, Tail...>: std::conditional_t<
  std::is_same<T, Head>::value, 
  std::true_type,
  is_any_of<T, Tail...>>
{};

現在我們可以SFINAE結束,使用幾乎英文措辭的enable_if

#include <type_traits>
#include <string>

template<
  class T,
  class = std::enable_if_t<is_any_of<T, int, float, unsigned, double>::value>
>
void foo(std::string &&str, T value) {}


int main()
{
  foo(std::string{"hello"}, 3);
  foo(std::string{"world"}, '0'); //compile-time error
}

SFANIE是一種語言功能,一種工具,用於或濫用某些人說要達到你所要求的,

標准庫組件std :: enable_if允許創建替換失敗,以便根據在編譯時評估的條件啟用或禁用特定重載。 僅供參考http://en.cppreference.com/w/cpp/language/sfinae

請注意, std::conditional_t<>std::enable_if_t<>分別來自std::conditional<>::typestd::enable_if<>::type 您可以在代碼中簡單地替換這些,但是應該在enable_if之前放置typename關鍵字。

我知道我參加聚會遲到了,但也許有人會覺得這很有用。

C++20開始,可以使用約束概念來過濾模板中可能的typename

語法如下:

template <typename T>
requires std::is_integral_v<T>
auto func(T any_integer) {
  ...
};

// Or, you can also do:

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

template <Integer T>
auto func(T any_integer) {
  ...
};

// Or, an even better approach:

auto func(Integer auto any_integer) {
  ...
};

我更喜歡最后一個,因為它又好又干凈。 但那只是我的個人意見。

以下是對func()的一些有效調用:

func(int{});         // OK!
func(long{});        // OK!
func(bool{});        // Yes, it's OK too!
func(char{});        // Yes, it's OK too!

現在,對func()的一些無效調用:

func(double{});      // Compiler error!
func(std::string{}); // Compiler error!

編譯器還將根據您的使用情況給出干凈的錯誤消息:

注意:候選人:'模板需要 is_integral_v void func(T)'

或者

注意:候選人:'模板需要整數自動函數(T)'

或者

注意:候選人:'模板需要 Integerauto:15 auto func(auto:15)'

參考:

  1. https://en.cppreference.com/w/cpp/types/is_integral

暫無
暫無

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

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