简体   繁体   English

模板C ++错误:无法推断出模板参数

[英]Templates C++ error : could not deduce template argument

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>' 错误C2784:'void printInstrumentDetail(const I * const)':无法从'std :: vector <_Ty>'推导出'const I * const'的模板参数

#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();
}

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函数的指针来解决此问题,如下所示:

printInstrumentDetail(&band[0]);

But really, you'd be much better off modifying printInstrumentDetail to take a container or a pair of iterators: 但实际上,最好将printInstrumentDetail修改为采用一个容器或一对迭代器:

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. 对功能的定义进行适当的修改。

Pass the pointer to vector 将指针传递给vector

printInstrumentDetail(&band);   

and inside printInstrumentDetail 和内部printInstrumentDetail

(*a)[i]->getName();

Well, first off I don't believe you can pass a vector as a const * I const at 好吧,首先,我不相信您可以将向量作为const * I const传递给

printInstrumentDetail(band); printInstrumentDetail(band);

Vector cannot be just cast to a pointer. 向量不能仅转换为指针。 One working solution would be something like: 一种可行的解决方案是这样的:


template <typename T>
void printInstrumentDetail( const std::vector<T*>& band )
{
    for ( size_t i = 0; i < band.size(); ++i )
        cout << "The details for " << band[i]->getName()
             << ": " << band[i]->print();
}

And there are many others, including iterators, functors, STL algorithms, etc. 还有很多其他东西,包括迭代器,函子,STL算法等。

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++. 但是要符合C ++中常见的模式。 You should pass the beginning and end of the sequence as parameters. 您应该将序列的开头和结尾作为参数传递。 ie change your function to take itertors rather than a pointer. 即更改您的函数以迭代器而不是指针。

Instead of passing the pointer: 而不是传递指针:

printInstrumentDetail(const I * const a)  

you can pass the reference: 您可以传递参考:

printInstrumentDetail(const I& a)

Everything else stays unchanged. 其他所有内容保持不变。

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. 首先,似乎根本没有理由将PrintInstrumentDetail用作模板–它可以使用指向基类的指针,并且除非您可能具有其他类型的getName()print()成员,它可以被应用,它可以/应该/应该只使用指向基类的指针。

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. 与其在每个Instrument中使用一个成员函数,以及在整个Instrument上循环使用PrintInstrumentDetail,我都想着要为Instrument定义operator<< ,并使用标准算法来打印出细节。

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. 首先,除非您要处理的是非常不寻常的乐器,否则黄铜乐器上的阀门数量将永远固定-因此,它不应具有SetValve()成员。 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. 弦乐器根本没有阀门(至少大多数普通的阀门没有阀门),因此它们不应该具有SetValves()GetValves()或任何其他与阀门有关的东西。

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. 编辑:另一件事:使用band.size()循环遍历band中的所有乐器,而不是在各处硬编码6

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM