2

我正在构建一个旨在实现高性能计算的数字 C++ 库(当然,双重类型将是主要的算术类型)。因此,我大量使用模板元编程。描述我想要构建的内容以及我的“问题”何时发生可能很难阅读,因此我创建了一个玩具示例来“模拟”我想要做的事情。

考虑到我想设计一种方法,它需要一个容器,根据一些常数缩放其内容并返回缩放数字的总和。为简单起见,假设我希望它在大小为 3 的容器上工作。常量可能会有所不同,因此在编程时,程序员(lib 的用户)将不得不提供它们。问题是这些常量可以是单精度或双精度,可以用作模板参数。

不过,另一方面,我希望编译器发出代码,就像我对常量进行了硬编码一样。

考虑以下代码:

#include <iostream>
#include <vector>

#include <boost/array.hpp>

using namespace std;

template<class T, class Coefs>
struct scale_add{

    Coefs coefs;    

    template <class Iterator>
    T apply(Iterator it){
       return coefs[0] * (*(it)) + coefs[1] * (*(it + 1)) + coefs[2] * (*(it + 2));
    }
};

template <class T>
struct my_coefs : public boost::array<T, 3>{
    my_coefs() {
        (*this)[0] = static_cast<T>(3.0);
        (*this)[1] = static_cast<T>(2.7);
        (*this)[2] = static_cast<T>(4.78);
    }
};

int main(){

    vector<double> my_vec(3, 9.1) ;
    typedef scale_add<double,  my_coefs<double> > my_scale_add;
    my_scale_add msa;
    double result = msa.apply(my_vec.begin() );
    cout << result << endl;
    return 0;
    }

如您所见,程序员将能够创建 my_scale_add 之类的类型!这是我目前的设计解决方案。我试图将“浮点数”表示为带有函数 value() 的结构,该函数将返回数字:

struct a1{
    typedef double type;
    static double value(){
        return 0.5;
    }
};

通过这种方式,我将类型放入类型列表等。唯一的问题是它可能会令人困惑,并且可能会面临类型重新定义等。但是当我编写类似 cout << a1::value() * 4.0 <<结束;编译器将内联它(根据我的一些参考资料)。

所以我的问题是,我怎样才能获得第二种方式的行为(a1::value()),而无需将类型打包到类型列表等中而产生巨大的编程开销?你能提出一种更有效的方式来表达第一个代码(好吧,这可以被认为是一个坏问题)?最后,我想说我不确定这个问题是否适合 stackoverflow,而且,我是 C++ 新手,不得不从什么是头文件跳转到什么是模板元编程,所以我可能忽略了中间的一些信息,这意味着我可能会问一些微不足道的事情。先感谢您 !

4

1 回答 1

0

虽然我不完全理解您的意思,但我认为以下代码可能符合您的要求。

template<typename Container>
struct scale_add
{
     typedef typename Container::traits_type type;

     Container Impl ;
     template<typename Iterator>
     type apply( Iterator First ) {
          return std::inner_product( std::begin(Impl) , std::end(Impl) ,
                                     First , type(0) );
     }
};

template<typename K>
struct my_scale_add : public std::array<K , 3>
{
     typedef K traits_type ;

     my_scale_add() { 
          (*this)[0] = static_cast<K>( 1.0 );
          (*this)[1] = static_cast<K>( 2.0 );
          (*this)[2] = static_cast<K>( 3.0 );
     }
};

int main()
{
      std::vector<double> my_vec(3,9.1);
      scale_add<my_scale_add<double>> mObject ;

      std::cout << mObject.apply( std::begin(my_vec) ) << std::endl;

      return 0;
}
于 2012-09-19T05:29:14.447 回答