我需要在我正在撰寫的模板中對字串型別進行一些特殊處理,但是我遇到了固定大小的 char 陣列的問題。我知道我可以撰寫此答案中提到的代碼來創建包裝器:Const char array with template argument size vs. char pointer
但是我想知道是否有一種方法可以測驗這是否是來自具有靜態斷言的模板化函式中的 const char 陣列,如下所示:
template<typename T>
void f(T& val /* a handful of other params */ )
{
static_assert(
std::is_same_v < T, const char* > ||
std::is_same_v < T, char[N] > || // how do I get/discard N here?
std::is_same_v < T, std::string >
, "Unsupported type" );
}
我這樣做的動機是避免為所有有效型別組合使用大量函式簽名,同時仍確保只允許有效型別。出于幾個原因,撰寫所有這些型別宣告和定義是一場噩夢。但是由于字串可以出現在各種固定大小的陣列中,我不確定如何在沒有包裝器的情況下檢查它們以剝離長度資料,但隨后我又開始撰寫大量包裝器,這正是我想要避免的(如果有某種方法可以使用單個包裝器撰寫一個簡單的可重用測驗,那是可以的,但我無法弄清楚)。對于這樣的每個字串,如果我要在每次字串引數出現在引數串列中時手動添加一個包裝器,這顯然會使我需要撰寫的宣告和定義的數量增加一倍,從而創建大量冗余代碼。那么有沒有辦法確定一個型別是否是一個固定的陣列型別,然后才提取沒有長度的指標,以便我可以根據 const char* 檢查它?或者以某種方式忽略陣列長度并在我的斷言中檢查它是否是 char 型別陣列?
uj5u.com熱心網友回復:
您無法直接確定 a 是否T是這樣的陣列,但標準庫提供了用于確定給定型別是否已經是陣列的特征:std::is_array.
雖然std::is_array也接受char[],這可能是不可取的。在這種情況下,如果您有權訪問 C 20,則可以使用std::is_bounded_array. 如果您無權訪問 C 20,則實作一個相當簡單,或者如果您只想檢查char[N]:
template <class> struct is_bounded_char_array : std::false_type {};
template <size_t N>
struct is_bounded_char_array<char[N]> : std::true_type {};
template <class> struct is_bounded_array : std::false_type {};
template <class T, size_t N>
struct is_bounded_array<T[N]> : std::true_type {};
static_assert(!is_bounded_array<char>{});
static_assert(!is_bounded_array<char[]>{});
static_assert(is_bounded_array<char[42]>{});
然后,代替std::is_same_v < T, char[N] >,您可以說is_bounded_array<T>。
要從您的任何型別中獲取 a const char*,您可以使用std::string_view(t).data()而不是自己處理每個案例。
uj5u.com熱心網友回復:
由于型別衰減,這是不可能的;T 的結果型別(來自函式 foo)是 char*。您可以通過我的示例弄清楚,只需嘗試編譯它:
#include <type_traits>
template<typename T>
struct is_inbuild_array final : std::false_type{};
template<typename T, std::size_t N>
struct is_inbuild_array<T[N]> final : std::true_type{};
template<typename T>
void f(T val)
{
static_assert(
is_inbuild_array<T>::value,
"Unsupported type"
);
}
int main()
{
char array [] = "Test";
f(array);
}
但是你可以像這樣修改你的函式(使用通用參考):
template<typename T>
void f(T&& val)
{
static_assert(
is_inbuild_array<std::remove_reference_t<T>>::value,
"Unsupported type"
);
}
而且效果很好
uj5u.com熱心網友回復:
我最終這樣做是為了根據此處的其他答案實作檢測:
#include <type_traits>
template < typename Desired, typename Actual > struct is_bounded_type_array : std::false_type {};
template < typename Desired, typename Actual, std::size_t N >
struct is_bounded_type_array < Desired, Actual[N] > : std::conditional_t < std::is_same_v < Actual, Desired >, std::true_type, std::false_type > {};
template < typename Desired, typename Actual >
inline constexpr bool is_bounded_type_array_v = is_bounded_type_array < Desired, Actual > ::value;
然后我可以在我的函式中像這樣使用它:
template<typename T>
void test(const T& value)
{
std::cout << is_bounded_type_array_v<char, T> << std::endl;
// or
static_assert(is_bounded_type_array_v<char, T>, "Must be bounded array of type char");
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/448797.html
下一篇:查找并洗掉字串上略有不同的子字串
