Search code examples
c++templatesgeneric-programming

Conversion to non-scalar type requested


In a homework assignment on generic programming, a program is not compiling. I'm supposed to fix this by inserting code only to the specified location and changing nothing else. I've attempted to do so by overloading operators to make the compiler understand what they mean for that custom type, but I still get the same errors. I'm now at a loss.

#include <iostream>

using namespace std;

template <typename T>
struct TripleData {
    T m_first;
    T m_second;
    T m_third;  
    T getMean() {
        return (m_first + m_second + m_third)/3;
    }

    // INSERT CODE HERE
    void operator = (const T & value) {
        m_first = m_second = m_third = value;  
    }

    void operator += (const TripleData & tridata) {
        m_first += tridata.m_first;
        m_second += tridata.m_second;
        m_third += tridata.m_third;
    }

    T & operator / (const T & divisor) {
        return m_first/divisor;
    }
    //END OF INSERTED CODE
};

template <typename T, int N>
class GenericStaticMatrix {
    T m_data[N];
public:
    T & operator()(int i) {
        return m_data[i];
    }
    int getSize() const {
        return N;
    }
    T getMean() const {
        T sum = 0;                            //Error: conversion from 'int' to non-scalar type 'TripleData<double>' requested
        for (int i=0;i<N;i++) sum+=m_data[i]; 
        T ret = sum/(double)N;                //Error: conversion from 'double' to non-scalar type 'TripleData<double>' requested
        return ret;
    }
};


int main() {

    const int size = 10;
    int i;     
    GenericStaticMatrix<TripleData<double>,size> gsm_tdd;

    for (i=0;i<size;i++) {
        gsm_tdd(i).m_first = 1.1 + i;
        gsm_tdd(i).m_second = 2.2 + i;
        gsm_tdd(i).m_third = 3.3 + i;
    }

    cout << gsm_tdd.getMean().m_first <<endl;
    cout << gsm_tdd.getMean().m_second <<endl;
    cout << gsm_tdd.getMean().m_third <<endl;

    return 0;
}

Thanks in advance!


Solution

  • The code that needs to run generically for TripleData<double> is:

    T sum = 0;                // (A)
    sum += m_data[i];         // (B)
    T ret = sum / (double)N;  // (C)
    

    Just work backwards from the implicit interface that this code implies.

    // (A) implies non-explicit construction from an int
    TripleData(int ); 
    
    // (B) implies operator+=, you have this one almost right
    TripleData& operator+=(const TripleData& rhs);
    
    // (C) implies division by a **scalar** - this should NOT modify the object
    TripleData operator/(double ) const;
    

    You're missing (A) completely - you wrote an assignment operator, but T x = y; isn't assignment, it's copy-initialization. (B) is basically fine, and (C) you're taking the wrong type of operand. We're dividing by a double, not by a TripleData<double>.