【问题标题】:Variadic template function with no arguments不带参数的可变模板函数
【发布时间】:2020-05-14 23:45:58
【问题描述】:

我想编写一个函数,它将根据函数的类型而不是参数进行操作。因此,该函数不接收基于模板的参数。一般的要点是这样的:

#include <iostream>

void func() {
    std::cout<<"End marker\n";
}

template <typename Type, typename... T>
void func() {
    std::cout<<"Type sizeof "<<sizeof(T)<<"\n";

    func<T...>();
}

int main() {
    func<int, int, int>();
}

这当然不能编译。我试过这样做:

template <typename Type, typename... T>
void func() {
    std::cout<<"Type sizeof "<<sizeof(T)<<"\n";

    if( sizeof...(T)!=0 )
        func<T...>();
}

但是,这不起作用。 func&lt;T...&gt; 可能不会被评估,但它确实需要是可编译的。

有没有我想念的方法来做到这一点?

【问题讨论】:

  • if constexpr?
  • @Quentin,是的,谢谢。但是,这并不能解决一般情况。我需要定义一个用func&lt;&gt;() 调用的函数,否则会以其他方式失败。
  • @user1810087 在某种意义上说“它不能用函数来完成”,那么是的,它确实:-(。我已经有一个基于结构的实现。它相当 i> 更复杂。

标签: c++ templates visual-c++ variadic-templates specialization


【解决方案1】:

您可以通过将func 设为“模板函数”(实际上并不使用模板)来使您的原始设置正常工作,例如:

template<int = 0>
void func() {
    std::cout<<"End marker\n";
}

template <typename Type, typename... T>
void func() {
    std::cout<<"Type sizeof "<<sizeof(Type)<<"\n";

    func<T...>();
}

您的第二个可以使用if constexpr 工作,所以func&lt;&gt;() 不会被编译。

【讨论】:

  • 这总是输出4?看here
  • @NutCracker 我假设他们想要每种类型的大小(而不是奇怪的std::integer_sequence)。 func&lt;char, char[2], char[3]&gt;(); 例如输出 1、2、3。
  • 嗯,在这种情况下,问题没有正确定义
【解决方案2】:

使用折叠表达式(在 C++17 中),您可以这样做:

template <typename... Ts>
void func()
{
    ((std::cout << "Type sizeof " << sizeof(Ts) << "\n"), ...);
    std::cout << "End marker\n";
}

这甚至可以在 C++11 中完成,但会更冗长:

template <typename... Ts>
void func()
{
    const int dummy[] = {((std::cout << "Type sizeof " << sizeof(Ts) << "\n"), 0)...};
    static_cast<void>(dummy); // Avoid warning for unused variable.
    std::cout <<"End marker\n";
}

Demo

【讨论】:

    【解决方案3】:

    您可以将非模板函数func 变成接受零模板参数的可变参数模板函数。然后让 SFINAE 在参数个数不为零的情况下移走这个模板函数。

    以下应该可以工作:

    #include <iostream>
    #include <type_traits>
    
    template <typename... Ts>
    typename std::enable_if<sizeof...(Ts) == 0>::type func() {
        std::cout<<"End marker\n";
    }
    
    template <typename T, typename... Ts>
    void func() {
        std::cout << "Type sizeof " << sizeof(T) << "\n";
    
        func<Ts...>();
    }
    
    int main() {
        func<int, int, int>();
    }
    

    但是,请注意:

    (8) 模板的有效性可以在任何之前检查 实例化。 [ 注意:知道哪些名称是类型名称允许 以这种方式检查的每个模板的语法。 —— 尾注 ] 程序格式错误,不需要诊断,如果:[..] (8.3) 每 可变参数模板的有效特化需要一个空模板 参数包...

    来源here

    更新

    这也可以:

    #include <iostream>
    #include <type_traits>
    
    void func() {
        std::cout<<"End marker\n";
    }
    
    template <typename T, typename... Ts>
    void func() {
        std::cout << "Type sizeof " << sizeof(T) << "\n";
    
        if constexpr (0 == sizeof...(Ts))
            func();
        else
            func<Ts...>();
    }
    
    int main() {
        func<int, int, int>();
    }
    

    【讨论】:

    • template &lt;typename... Ts&gt; typename std::enable_if&lt;sizeof...(Ts) == 0&gt;::type func() 使模板格式错误:"程序格式错误,不需要诊断,如果: (8.3) — 可变参数模板的每个有效特化都需要一个空模板参数包,”.
    • @Jarod42 tnx。我会用这个笔记更新我的答案。
    猜你喜欢
    • 2012-05-03
    • 1970-01-01
    • 1970-01-01
    • 2014-09-08
    • 1970-01-01
    • 2021-10-01
    • 2016-10-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多