[英]C++ how to check the signature of a template parameter class at compile time
[英]Check with which template parameter a class was instantiated (compile time)
我嘗試編寫一個元函數type_par_same_as
,只要true_type
的模板參數與給定類型匹配,它就會選擇 true_type :
#include <type_traits>
#include <concepts>
#include <string>
#include <vector>
#include <cstdio>
template <template <typename...> class Template, typename T>
struct type_par_same_as_impl : std::false_type {};
template <template <typename...> class Template, typename... Args>
struct type_par_same_as_impl<Template<Args...>, Args...> : std::true_type {};
template <template <typename...> class Template, typename... Args>
concept type_par_same_as = type_par_same_as_impl<Template, Args...>::value;
int main()
{
std::vector<int> vint;
std::vector<std::string> vstring;
if constexpr (type_par_same_as<decltype(vint), int>) {
printf("Vector instantiated with type int!\n");
}
}
這是我得到的:
<source>:11:56: error: type/value mismatch at argument 1 in template parameter list for 'template<template<class ...> class Template, class T> struct type_par_same_as_impl'
11 | struct type_par_same_as_impl<Template<Args...>, Args...> : std::true_type {};
| ^
<source>:11:56: note: expected a class template, got 'Template<Args ...>'
我的方法是原始模板模板參數只接受模板的任何特化,例如std::vector
(無類型)。 然后我 SFINAE-out class 與模板專業化不匹配的類型 Template<Args...> (例如std::vector<int>
如果 int 被指定為Args
)並且我應該收到所有true_type
類型的 true_type 其中這個可以做到。 但我的邏輯似乎在某些時候不對勁。 我go哪里錯了?
下面是編譯的方法:
template <class Template, typename... T>
struct type_par_same_as_impl : std::false_type {};
template <template <typename...> class Template, typename... Args>
struct type_par_same_as_impl<Template<Args...>, Args...> : std::true_type {};
template <class Template, typename... Args>
concept type_par_same_as = type_par_same_as_impl<Template, Args...>::value;
但它不適用於您的測試用例,因為std::vector<int>
實際上是std::vector<int, std::allocator<int>>
並且您只傳遞兩者中的int
。 所以你需要:
int main()
{
std::vector<int> vint;
std::vector<std::string> vstring;
if constexpr (type_par_same_as<decltype(vint), int, std::allocator<int>>) {
printf("Vector instantiated with type int!\n");
}
}
這可以按最初的預期工作,如果擴展lorro 的答案, Args...
被放置在非推導的上下文中,因此它們僅從顯式傳遞的模板參數推導,而不是std::vector
的參數推導通過使用std::type_identity
實例化:
#include <type_traits>
#include <vector>
template <typename Template, typename... Args>
struct type_par_same_as_impl : std::false_type {};
template <template <typename...> typename Template, typename... Args>
struct type_par_same_as_impl<Template<std::type_identity_t<Args>...>, Args...>
: std::true_type {};
template <typename Template, typename... Args>
concept type_par_same_as = type_par_same_as_impl<Template, Args...>::value;
static_assert(type_par_same_as<std::vector<int>, int, std::allocator<int>>);
static_assert(type_par_same_as<std::vector<int>, int>);
static_assert(not type_par_same_as<std::vector<int>, float>);
我只是想添加一個我剛剛找到的解決方案,它可能更加通用。
與其比較第一個模板參數,不如提取第 n 個模板參數並使用慣用的std::is_same<U,T>
來比較它。 這樣用戶就可以自由選擇實際比較哪個模板參數:
#include <type_traits>
#include <concepts>
#include <string>
#include <vector>
#include <tuple>
#include <cstdio>
template<std::size_t, typename>
struct nth_targ_of;
template<std::size_t N, template <typename...> class Template, typename... Args>
struct nth_targ_of<N, Template<Args...>> : std::tuple_element<N, std::tuple<Args...>> {};
template<std::size_t N, typename T>
using nth_targ_of_t = nth_targ_of<N, T>::type;
int main()
{
std::vector<int> vint;
std::vector<std::string> vstring;
if constexpr(std::same_as<nth_targ_of_t<0, decltype(vint)>, int>) {
printf("Vector instantiated with type int!\n");
}
if constexpr(std::same_as<nth_targ_of_t<0, decltype(vstring)>, std::string>) {
printf("Vector instantiated with type string!\n");
}
}
Output:
Vector instantiated with type int!
Vector instantiated with type string!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.