tags:

views:

249

answers:

7

I am trying ot add a function template that will print if it contains precision values or valves and the value. The rest of the program works except this function. I am not sure what I am doing wrong but the error I recieve is:

error C2784: 'void printInstrumentDetail(const I *const )' : could not deduce template argument for 'const I *const ' from 'std::vector<_Ty>'

#include <iostream>
#include <vector>
#include <iomanip>
#include <string>
#include "Instruments.h"
#include "Brass.h"
#include "Strings.h"

using namespace std;

//template<typename I>           <---Problem
//void printInstrumentDetail(const I * const a)
//{
//   for (size_t i = 0; i < 6; i ++)
//  {
//   cout << "The details for " << a[i]->getName()
//    << ": " << a[i]->print();
//  }
//}
int main()
{
    double total = 0;

    Strings violin("Violin", 553.90, 3);
    Strings cello("Cello", 876.45, 3);
    Strings viola("Viola", 200.50, 23);
    Brass tuba("Tuba", 1400.10, 1.23);
    Brass trumpet("Trumpet", 500.00, 4.32);
    Brass sax("Sax", 674.78, .99);

    vector <Instruments *> band(6);

    band[0] = &violin;
    band[1] = &tuba;
    band[2] = &cello;
    band[3] = &trumpet;
    band[4] = &viola;
    band[5] = &sax;

    cout << fixed << setprecision(2);

    cout << "The instruments in the band are:\n";
    //Get name and cost of each
    for (size_t i = 0; i < 6; i ++)
    {
     cout << band[i]->getName() << "  $" 
      << band[i]->getCost() << endl;
    }

    cout << "\nThen band is warming up..." << endl;
    //Get descrition of how sound is made of each
    for (size_t i = 0; i < 6; i ++)
    {
     cout << "This " << band[i]->getName()
      << " makes sounds by " ;
     band[i]->playSound();
    }
    cout << "\nTotal cost of the band is: $" ;
    //Get total cost of all instruments
    for (size_t i = 0; i < 6; i ++)
    {

     total = band[i]->getCost() + total;
    }
    cout << total << endl;

    //printInstrumentDetail(band);                     <--Problem

    return 0;
}

Here's the base class:

#ifndef INSTRUMENTS_H
#define INSTRUMENTS_H

#include <string>

using namespace std;

class Instruments
{
public:
    Instruments(string, double);

    void setName(string);
    virtual string getName();

    void setCost(double);
    virtual double getCost();

    virtual void print();

    virtual void playSound();

private:
    string name;
    double cost;
};
#endif

#include <iostream>
#include "Instruments.h"

using namespace std;

Instruments::Instruments(string n, double c)
{
    name = n;
    cost = c;
}
void Instruments::setName(string n)
{
    name = n;
}
string Instruments::getName()
{
    return name;
}
void Instruments::setCost(double c)
{
    cost = c;
}
double Instruments::getCost()
{
    return cost;
}
void Instruments::print() 
{

}
void Instruments::playSound()
{
    //empty
}

Derived class Bass:

#ifndef BRASS_H
#define BRASS_H

#include <string>
#include "Instruments.h"

using namespace std;

class Brass : public Instruments
{
public:
    Brass(string, double, double);

    void setPrecisionValue(double);
    double getPrecisionValue();
    void print() ;
     void playSound();

private:
    double precision;
    string sound;
};
#endif

#include <iostream>
#include "Brass.h"

using namespace std;

Brass::Brass(string n, double c, double p)
:Instruments(n, c)
{
    precision = p;
}
void Brass::setPrecisionValue(double p)
{
    precision = p;
}
double Brass::getPrecisionValue()
{
    return precision;
}
void Brass::print() 
{
    cout << getPrecisionValue() << endl;
}
void Brass::playSound()
{
    cout << "blowing in a mouthpiece." << endl;
    Instruments::playSound();
}

Derived class Strings:

#ifndef STRINGS_H
#define STRINGS_H

#include <string>
#include "Instruments.h"

using namespace std;

class Strings : public Instruments
{
public:
    Strings(string, double, int);

    void setValves(int);
    int getValves();
    void print();
    void playSound();

private:
    int valves;
};
#endif

#include <iostream>
#include "Strings.h"

using namespace std;

Strings::Strings(string n, double c, int v)
    :Instruments(n, c)
{
    valves = v; 
}
void Strings::setValves(int v)
{
    valves = v;
}
int Strings::getValves()
{
    return valves;
}
void Strings::print() 
{
    cout<< getValves() << endl;
}
void Strings::playSound()
{
    cout << "striking with a bow." << endl;
    Instruments::playSound();
}
A: 

Well, first off I don't believe you can pass a vector as a const * I const at

printInstrumentDetail(band);

A: 

Pass the pointer to vector

printInstrumentDetail(&band);

and inside printInstrumentDetail

(*a)[i]->getName();
aJ
If you do that the operator[] will not work as expected. You are de-referencing a vector[]*. This will give you the next vector not the next element in the vector.
Martin York
I got it to work with this but my other problem was:a[i]->print(); included in my cout......duh caught that as I was trying your resolution. Thanks bunches to all who helped!!
lilnan
Why not pass the vector by reference rather than a pointer?
Martin York
In fact, If I want to better the solution I would go for pair of iterators.
aJ
+6  A: 

Well, the problem is that your template requires a pointer:

template<typename I>   
void printInstrumentDetail(const I * const a);

but you're giving it a vector, not a pointer:

vector <Instruments *> band(6);
...
printInstrumentDetail(band);

You can hack your way around this by passing a pointer to the printInstrumentDetail function, like so:

printInstrumentDetail(&band[0]);

But really, you'd be much better off modifying printInstrumentDetail to take a container or a pair of iterators:

template <typename ContainerT>   
void printInstrumentDetail(const ContainerT& a)

or

template <typename IteratorT>
void printInstrumentDetail(IteratorT first, IteratorT last)

with the appropriate modifications to the definition of the function.

James McNellis
Or: modify it to take only a value, and use it with `std::for_each`.
PiotrLegnica
Now I get error:error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'void' (or there is no acceptable conversion)I changed it:template <typename I> //<---Problemvoid printInstrumentDetail(const I i < 6; i ++) { cout << "The details for " << a[i]->getName() << ": " << a[i]->print(); }}and called it with the same:printInstrumentDetail(band);Do I need and overload opreator to fix the error?
lilnan
oops sorry about the messeged up message
lilnan
A: 
Nikolai N Fetissov
A: 

You are trying to pass an object to an interface that wants a pointer.

void printInstrumentDetail(const I * const a)

Convert this to a reference.

void printInstrumentDetail(I const I& a)

But to conform to the pattern that is common in C++. You should pass the beginning and end of the sequence as parameters. ie change your function to take itertors rather than a pointer.

Martin York
A: 

Instead of passing the pointer:

printInstrumentDetail(const I * const a)

you can pass the reference:

printInstrumentDetail(const I& a)

Everything else stays unchanged.

avp
A: 

First of all, there seems to be no reason for PrintInstrumentDetail to be a template at all -- it works with pointers to the base class, and unless you're likely to have other types with getName() and print() members to which it might be applied, it can/could/should just work with pointers to the base class.

Second, I'd think hard about changing how you do the job. Instead of a member function in each Instrument, and PrintInstrumentDetail to loop over all the instruments, I'd think hard about defining operator<< for Instrument, and using a standard algorithm to print out the details.

Looking at it, I think a few other things should change as well. First of all, unless you're dealing with really unusual instruments, the number of valves on a brass instrument is fixed forever -- so it should NOT have a SetValve() member. Rather, the number of valves should be set during construction, but not be open to change afterwards.

String instruments don't have valves at all (at least most normal ones don't), so they shouldn't have SetValves(), GetValves(), or anything else related to valves.

Likewise, unless you're doing something pretty unusual, the cost of an instrument can never change -- you paid what you paid, so the cost should be set during construction, and not open to later alteration.

Edit: one other thing: instead of hard-coding 6 everywhere, use band.size() to loop over all the instruments in the band.

Jerry Coffin
Its an assignment. The instructor requested that we have sets and gets for each data member, use of a template function. As for Strings having valves ??? I just went off what she gave us for a sample output and her sample had "The details for violin has 3 valves. The details for Cello has 3 valves. etc...." I just needed to get the same output.
lilnan
But thanks for the valuable information. I do know that many of the assignments are not efficient coding and its nice to know what is out in the real world of code. I think the ackwardness to some of these assignments are just to see if we have knowledge on a specific task even if ackward.Thanks again!!
lilnan