Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ c++;更广义的算子模板_C++_Templates_Operators - Fatal编程技术网

C++ c++;更广义的算子模板

C++ c++;更广义的算子模板,c++,templates,operators,C++,Templates,Operators,所以我刚刚学习了decltype(谢谢大家)。我现在可以编写非常好的向量模板,其性能实际上优于ValArray(!): 模板 向量运算符*(常数向量和A、常数向量和B){ 向量C=向量(A.size()); typename向量::常量迭代器a=a.begin(); typename向量::常量迭代器b=b.begin(); typename向量::迭代器c=c.begin(); while(a!=a.end()){ *c=(*a)+(*b); A++;B++;C++; } 返回C; }

所以我刚刚学习了decltype(谢谢大家)。我现在可以编写非常好的向量模板,其性能实际上优于ValArray(!):

模板
向量运算符*(常数向量和A、常数向量和B){
向量C=向量(A.size());
typename向量::常量迭代器a=a.begin();
typename向量::常量迭代器b=b.begin();
typename向量::迭代器c=c.begin();
while(a!=a.end()){
*c=(*a)+(*b);
A++;B++;C++;
}
返回C;
}  
在我们允许操作符(“*”)本身作为模板参数的意义上,是否有可能使这种模板更加“元”?也就是说,如果在*c=(*a)op(*b)中使用了适当的运算符op,则有一个适用于*、+、%等的单一模板定义


我打赌不是,但那会很好

正如您所料,这个答案是“否”:

但是,您可以使用预处理器生成以下函数:

#define OPERATOR_BLOB(optype) \
    vector<…> operator optype (…) { … }

OPERATOR_BLOB(*)
OPERATOR_BLOB(+)
…
#定义运算符\u BLOB(optype)\
向量运算符optype(…){…}
运算符_BLOB(*)
运算符_BLOB(+)
…
使用
std::declval()
而不仅仅是
T()
,它可能没有默认构造函数(因为std::vector不需要默认构造函数,只需要副本构造函数)。另外,对于类型、引用和右值引用的正确性和转发,要非常确定,类可能会对值、引用、常量引用和右值引用执行不同的操作。用几个类来测试它

另外,请注意,由于未实现的特性,返回类型提取可能不适用于GCC中的复合赋值运算符

是的,我用指针包装器类中的参数化宏解决了这个问题:

比如说

#define PROXY_BINARY_OPERATOR(_) \
    template <class Arg> \
    decltype(std::declval<T&&>() _ std::declval<Arg&&>()) operator _ (Arg&& arg) \
    { \
        return std::forward<T>(get()) _ std::forward<Arg>(arg); \
    } \
    template <class Arg> \
    decltype(std::declval<const T&&>() _ std::declval<Arg&&>()) operator _ (Arg&& arg) const \
    { \
        return std::forward<T>(get()) _ std::forward<Arg>(arg); \
    }
#定义代理#u二进制#u运算符(#)\
模板\
decltype(std::declval()ustd::declval())运算符uz(Arg&&Arg)\
{ \
返回std::forward(get())\ustd::forward(arg)\
} \
模板\
decltype(std::declval()ustd::declval())运算符uz(Arg&&Arg)常量\
{ \
返回std::forward(get())\ustd::forward(arg)\
}

这本质上是
accumulate
的二进制版本,尽管
accumulate
本身已经可以用于类似的东西,尽管不是很对称。然而,真正的力量可能来自懒惰的评估包装器。。。。两个细节:您可能希望使用
C
reserve
的默认构造来确保它不需要增长,然后使用
push_back
(而不是使用
vector C=vector(a.size())
创建大小为的数组,并重写元素)。使用typedefs!它们有助于可读性,单个
typedef decltype(a.front()*B.front())结果\u type
将使代码更具可读性。避免向泛型代码添加不必要的需求(当前实现使用
T()
U()
,以及
result\U type()
强制存在默认构造函数)@DavidRodríguez-dribeas:我发现使用push\U-back比完整的declare/rewrite版本要慢得多,在我的测试用例中最多慢50%。@KerrekSB:我必须检查懒惰的评估包装,我对它们一无所知。@andyincridge:您执行测试的设置是什么?你提前预订了座位吗?请注意,
reserve()
调用将产生巨大的差异,因为它将确保进行单个内存分配(假设您保留了适当的大小),在这种情况下,它应该比您的方法更快。如果不是,我想知道您正在运行什么编译器、平台和测试。。。
#define PROXY_BINARY_OPERATOR(_) \
    template <class Arg> \
    decltype(std::declval<T&&>() _ std::declval<Arg&&>()) operator _ (Arg&& arg) \
    { \
        return std::forward<T>(get()) _ std::forward<Arg>(arg); \
    } \
    template <class Arg> \
    decltype(std::declval<const T&&>() _ std::declval<Arg&&>()) operator _ (Arg&& arg) const \
    { \
        return std::forward<T>(get()) _ std::forward<Arg>(arg); \
    }