簡體   English   中英

檢查 class 是用哪個模板參數實例化的(編譯時)

[英]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>);

在 Compiler Explorer 上試用

我只是想添加一個我剛剛找到的解決方案,它可能更加通用。

與其比較第一個模板參數,不如提取第 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.

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