簡體   English   中英

為可變參數化模板函數中的每種模板類型調用void函數?

[英]Call void function for each template type in a variadic templated function?

我的目標是編寫一個簡單的通用函數來注冊任意C ++類型的轉換器。 為了簡單起見,我只打印C ++類型名稱。 我希望能夠為任何類型調用通用的print_type_name函數,包括一次包含多種類型(可變):

template <typename T>
void print_type_name(void)
{
    std::cout << typeid(T).name() << std::endl;
}

對於以下情況,這可以正常工作:

print_type_name<int>();
print_type_name<std::string>();
print_type_name<std::vector<std::complex<float> > >();

但是,我需要能夠為可變參數模板中的每種類型調用此函數,例如(擴展時):

print_type_name<int, std::string, std::vector<std::complex<float> > >();

這是我想出的,但是很笨拙:

template <typename ...TS>
void noop(TS... ts) { }

template <typename T>
int real_print_type_name(void) {
    std::cout << typeid(T).name() << std::endl;
    return 0;
}

template <typename ...TS>
void print_type_name(void) {
    noop(real_print_type_name<TS>()...);
}

其中包括以下內容:

template <typename ...TS>
void other_function(void) {
    print_type_name<TS...>();
}

請注意,無用的noop函數和real_print_type_nameint返回類型,為了擴展參數包,必須將兩者都添加。 有沒有更干凈的方法可以做到這一點?

template <typename ...TS>
void print_type_name() {
    using expander = int[];
    (void) expander{ 0, (std::cout << typeid(TS).name() << '\n', 0)... };
}

或者,C ++ 17樣式:

template <typename ...TS>
void print_type_name(void) {
    (std::cout << ... << (typeid(TS).name() + "\n"s));
}

演示

這是一個輔助功能。 它使用隨機的黑暗魔法,但它的名字很清楚:

void do_in_order() {}

template<class...Fs>
void do_in_order( Fs&&...fs ) {
  using discard=int[];
  (void)discard{0, (void(
    std::forward<Fs>(fs)()
  ),0)... };
}

或在C ++ 17中:

template<class...Fs>
void do_in_order( Fs&&...fs ) {
  (void(std::forward<Fs>(fs)())...);
}

(好多了)。

隱藏了所有丑陋的地方。 它需要一組void()可調用對象並從左到右調用它們-依次執行任務,就像在罐子上說的那樣。

然后, print_type_names變為:

template<class...Ts>
void print_type_names() {
  do_in_order( print_type_name<Ts>... );
}

要么

template<class...Ts>
void print_type_names() {
  do_in_order( [&]{
    std::cout << typeid(Ts).name() << std::endl;
  }... );
}

如果您不想使用單個print_type_name函數並希望內聯它。

請注意,一些不合格的編譯器抱怨將整個lambda擴展為...

現場例子

我認為您可以這樣做:

void print_type_name()
{
    std::cout<<"\n";
}

template <typename T>
void print_type_name(const T& t)
{
    std::cout<<t<<" : of type "<<typeid(t).name()<<"\n";
}

template <typename T1, typename... Ts>
void print_type_name(const T1& t1, const Ts&... ts)
{
    // Head
    std::cout<<t1<<" : of type "<<typeid(t1).name()<<", ";
    // Tail
    print_type_name(ts...);
}

是否更清楚我不知道。

暫無
暫無

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

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