如何存储<t>类型的值

时间:2016-07-06 07:55:12

标签: c++ arduino

如何存储数据类型<T>的值?我尝试做的是拥有一个适用于longdouble类型的功能。例如,返回5个数字的中位数(因为现在我有两个类,一个用于long,一个用于double)。我不知道如何做的两件事:

  • 如何存储<T>
  • 是否可以从返回类型<T>的函数中调用返回类型为<T>的函数

这是非工作代码,剥离可读。代码适用于Arduino(或其他类似的微控制器)。谢谢。

//how to store custom type?
//in practice, this may be a single value, array,
//or struct with one of the members being T

T values[5]={2,6,8,9,11};

//public
template <typename T> T getFirst (){
  T result = getPos[0]; 
  return result;  
}

//private
template <typename T> T getPos (byte index){
  T result = values[index]; 
  return result;  
}

void setup() {
  // put your setup code here, to run once:
  double k;
  k=getFirst()
}

void loop() {
  // put your main code here, to run repeatedly:

}

编辑4,最终的想法: 由于一些用户报告的编​​辑太多,我决定删除所有内容。我只留下原来的问题。我将在一个新的,独立的anwser中给出我的最终发现。

3 个答案:

答案 0 :(得分:1)

修改此答案已不再适用,因为问题已大幅改变。 (结束编辑)

计算5个值的中位数的函数需要获得5个值作为参数。这可以是标准容器或指向遗留数组或一对迭代器的普通指针。该功能不需要关心这些值的存储。来电者存储它们。

template <typename T>
T median_of_5 (const std::array<T, 5>&); // a standard no-overhead container

template <typename T>
T median_of_5 (const T*); // a legacy array

template <typename Iter>
decltype(*std::declval<Iter>())
median_of_5 (Iter first, Iter last); // two iterators

// or another way
template <typename Iter>
typename std::iterator_traits<Iter>::value_type
median_of_5 (Iter first, Iter last); // two iterators

如果函数模板需要临时存储类型T的某些数据,只需在函数中声明它:

template <typename T>
T median_of_5 (const std::array<T, 5>&)
{
    T values[5]; // no problem here
    ...
}

如果您不需要使用泛型类型T在任何函数模板之外存储五个值,并且可以使用C ++ 14,则可以使用变量模板:

 template <typename T>
 T values[5] { 2,6,8,9,11 };

但这很可能不是你所需要的。

答案 1 :(得分:1)

你的意思是这样吗?

template<typename T>
class medianbuffer{
public:
    // Should work like this
    medianbuffer() { /**/ }
    ~medianbuffer() { /**/ } // "~" = destructor , no expecting to happen
    T getFirst (){
        T result = getPos(0);
        return result;
    }
    private:
    T getPos (byte index){
        T result = values[index];
        return result;
    }
    T values[5]={2,6,8,9,11};
};

使用模板typename的所有函数都必须在头文件AFAIK中定义。

然后,您将使用每种类型的一个medianbuffer类。所有功能仍然需要定义。

答案 2 :(得分:0)

所以,我现在有一些调查结果。

  • 在尝试您可以在线找到的所有内容之前,先创建新课程,然后再使用它。尝试使用<T>类型更好或仅使用这种方式(不知道何时)。
  • 不要为.h和.cpp使用单独的文件。我不确定为什么这是一个问题,因为编译器毕竟是将所有文件“合并”在一起,但事实证明,如果你不遵循这个建议,你会得到聪明的人可以理解的错误 - 但是你不会,而且还有 - 浪费了两天。

在写这篇文章的那一刻,这就是我所知道的。我的猜测是,在接下来的几年中,很多人可能会在这里绊倒,并且知道更好的人试图给出一些更好的解释,或者至少填补空白。

/*Before class with prototypes, indicate that Template T will be used
   not sure when to use first or second line, seems that both work in this scenario*/
    //template<class  T>
    template<typename  T>
    class medianbuffer{
        public:    
        medianbuffer() { /**/ } //since no cpp will be used, do not forget to create proper functions {} in this file
        ~medianbuffer() { /**/ } 
        T getFirst();
        //you may also try to define it here
        //T getFirst();{
           // T result = getPos(1);
           // return result;
        //}
        private:
        T getPos (byte index){
            T result = values[index];
            return result;
        }
        T values[5]={2,6,8,9,11};
    };

    //Here is one of your bigest time waste, and it's not an obvious one - put all in one file!
    /*The following part is usually in cpp files, but you will see a lot of "undefined" or similar warnings
    Because templates are compiled when required, this forces a restriction for multi-file projects:
    the implementation (definition) of a template class or function must be in the same file as its declaration.
    That means that we cannot separate the interface in a separate header file,
    and that we must include both interface and implementation in any file that uses the templates.
    http://www.cplusplus.com/doc/oldtutorial/templates/
    */
    //if writing methods here, remember that every method must have "template" in front,
    //do not forget to put <T>, since you will get a lot of cryptic errors
    template<typename  T>
    T medianbuffer<T>::getFirst(){
        T result = getPos(1);
        return result;
    }

    //type of T is actually passed to its class this way
    medianbuffer <double>mb_d;
    medianbuffer <int> mb_i;

    void setup() {
        Serial.begin(57600);
        debug();
    }

    void debug(){

        //class instantiated as double, you can use it normaly
        double first_d=mb_d.getFirst();
        Serial.print("\n double type --> ");
        Serial.print(first_d);

        //class instantiated as int
        int first_i=mb_i.getFirst();
        Serial.print("\n int type    --> ");
        Serial.print(first_i);
    }
    void loop() {
        // put your main code here, to run repeatedly:

    }

先生,谢谢。和FredyKay,非常感谢你的帮助。