[英]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種類型是什么,所以這是一個有兩種類型int
和float
的例子。
using myType = std::enable_if<
std::is_same<int, T>::value ||
std::is_same<float, T>::value, T >::type;
只有當T
完全是int
或float
myType
存在。 希望有所幫助!
<type_traits>
允許您將邏輯推廣到類模板中。 這是如何工作的我們采取模板參數T
和Ts
參數包,我們開始檢查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<>::type
和std::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)'
參考:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.