如何将矢量元素提供给模板

Posted

技术标签:

【中文标题】如何将矢量元素提供给模板【英文标题】:How to feed vector elements to a template 【发布时间】:2013-07-21 06:28:07 【问题描述】:

我需要使用与模板参数相同类型的元素列表,所以我使用的是向量,但我不知道如何进行这项工作

#include <iostream>
#include <cstdint>
#include <vector>

template <uint8_t VAL>
void foo()

    std::cout << "__" << std::endl;
;

template <>
void foo<3>()

    std::cout << "OK" << std::endl;
;

int main()

    std::vector<uint8_t> v =  2, 4, 5, 2, 3, 55 ;
    for (auto &k : v) 
        foo<k>();
    
    return (0);

编译器基本上抱怨k不是a constant expression,问题是我不知道如何修改它以使其工作,我需要一些数据结构来迭代,所以我需要保留矢量,我需要一个模板来简化我的生活,所以我越看这个越觉得自己陷入了无限循环。

【问题讨论】:

不,这不是模板的用例。这是if (i == 3) cout &lt;&lt; "OK"; 的用例。 @H2CO3 你到底是什么意思?您可以模板化一个数值,这是肯定的,&lt;3&gt; 的重载只是为了检查模板调用中的某些内容。我需要一个数值模板。 @userXXX 我知道你可以使用 integer(不是任何数字)作为模板参数。虽然不是变量,但只是一个编译时常量。我的意思是我没有看到模板的必要性。这很可能是一个 XY 问题。 模板必须在编译时解析。这意味着您用作模板参数的任何内容都必须是编译时常量。这不仅意味着该值是在编译时设置的,而且它在语法上用作常量,而不仅仅是普通变量的值(就像您在此处所做的那样)。 @JerryCoffin 是的,事实上我的问题是如何将该向量转换为恒定编译时间的值集,真正的问题与模板无关。 【参考方案1】:

您可以使用可变参数模板来避免将列表实际存储在向量中,因此您只需将值直接传递给变量函数模板:

#include <iostream>

void print(int t) 
    static char const *s [] =  "__", "OK" ;
    std::cout << s[t == 3];


void print() 

template<typename... Args>
void print(int n, Args ... args) 
    print(n);
    print(args...);


int main() 
    print(2, 4, 5, 2, 3, 55);

结果:

________OK__

但是,正如您所见,这仍然需要在运行时评估与 3 的相等性。我不敢说它不能用模板专业化来完成,但至少我不知道如何如果可能的话。

【讨论】:

【参考方案2】:

如果无法在编译时间上轻松推断出需要进行的&lt;here&gt;,则不应使用模板。在这种情况下,k 不是常量表达式,因此您不能将其用作模板参数。

模板不是魔锤。它们有很多用例,但您不能绝对将它们用于所有事情。

在这个特定的 sn-p 代码中,foo 应定义为 void foo(uint8_t)


是的,事实上我的问题是如何将该向量转换为恒定编译时间的一组值,真正的问题与模板无关。

您也许可以使用可变参数模板来实现这一点。您可以直接在可变参数模板 (foo&lt;2, 4, 5, 2, 3, 55&gt;) 中使用整数常量,而不是使用向量。

我对它们不是很感兴趣,所以这需要一段时间。

编辑:杰瑞打败了我。

【讨论】:

但我可以轻松地重载模板来修改单个值的行为,但我无法使用您建议的其他解决方案来做到这一点。 根本不可能使用运行时值作为模板参数。模板是编译时特性。因此需要常量表达式。【参考方案3】:

如果您真的想要一种方法来迭代整数值的编译时常量列表:

#include <iostream>
#include <cstdint>

template <uint8_t VAL>
inline void foo()

    std::cout << "__" << std::endl;


template <>
void foo<3>()

    std::cout << "OK" << std::endl;


template <uint8_t... Values>
struct FooHelper 
  static void foo_all() 
  
;

template <uint8_t First, uint8_t... Rest>
struct FooHelper<First, Rest...> 
  static void foo_all() 
    foo<First>();
    FooHelper<Rest...>::foo_all();
  
;

template <uint8_t... Values>
void foo_all()

    FooHelper<Values...>::foo_all();


int main()

    foo_all<2, 4, 5, 2, 3, 55>();

虽然老实说我没有看到它的用例。

【讨论】:

【参考方案4】:

编译器无法在编译时推断 k 的可能值,所以我看不出这是如何工作的?

【讨论】:

这就是我需要解决的问题,我通常不会对已经工作的事情提出问题:D【参考方案5】:

不,这不适用于非常量表达式。让它成为一个普通的旧函数:

#include <iostream>
#include <cstdint>
#include <vector>

void foo(uint8_t VAL)

    if(VAL == 3)
        std::cout << "OK" << std::endl;
    else
        std::cout << "__" << std::endl;
;

int main()

    std::vector<uint8_t> v =  2, 4, 5, 2, 3, 55 ;
    for (auto &k : v) 
        foo(k);
    
return (0);

【讨论】:

以上是关于如何将矢量元素提供给模板的主要内容,如果未能解决你的问题,请参考以下文章

按键擦除矢量元素

如何使用矢量元素将项目添加到结构中?

如何将矢量(或类似)传递给可变参数模板

如何将 ngFocus/ngBlur 委托给指令的模板 <input> 元素?

如何将不同的类传递给元素指令

对矢量的某些元素执行操作