在模板类中使用模板方法

时间:2017-10-27 23:28:19

标签: c++ c++11 templates

为什么它期待Struct1以及如何格式化它以便我可以修改任何结构中的属性?

我有一个模板类,我用来修改包含相同属性名称的3个结构中的数据,它们碰巧使用不同的数据类型。

我正在尝试在我的模板类中使用模板方法,所有内容似乎都按照我预期的方式在各种实例化时使用模板类。

GenericClass<Struct1> inventory[1000];
GenericClass<Struct2> machines[1000];
GenericClass<Struct3> physicalStructures[1000];

(是的,我知道向量存在,一起播放,我尽可能包含尽可能少的代码)这就是说,当我尝试更改结构的一个属性时,我得到一个错误,指出它正在期待struct,而不是采用我提供的任何数据类型。

Main.cpp:39:28: error: no viable conversion from 'int' to 'Struct1'
inventory[0].setIdentifier(1);

我已经检查了这3个引用(以及其他一些引用),但它们似乎并不像我在其中任何一个那样做。 How to define template function within template class in *.inl file

Template class with template function

https://isocpp.org/wiki/faq/templates

以下是我的代码示例。

template <class Type>
class GenericClass
{ 
private:
  Type Identifier;
public:
  void setIdentifier(Type Param);
  Type getIdentifier();
};


/* Struct prototypes
************************/
struct Struct1
{
private:
  int Identifier;
  string Description;
  float Value;
}

struct Struct2
{
private:
  long int Identifier;
  string Description;
  float Value;
};

struct Struct3
{
private:
 string Identifier;
 string Description;
 double Value;
};


int main()
{
  GenericRecord<Struct1> inventory[1000];
  GenericRecord<Struct2> machines[1000];
  GenericRecord<Struct3> physicalStructures[1000];
  inventory[0].setIdentifier(1);
}


template <class Type>
void GenericRecord<Type>::setIdentifier(Type Param)
{
  Identifier = Param;
}
template <class Type>
Type GenericRecord<Type>::getIdentifier()
{
  return Identifier;
}

返回方法也不起作用,我预计它们都会因为类似的原因而失败。

同样,为什么它期待Struct1以及如何格式化它以便我可以修改任何结构中的属性?

3 个答案:

答案 0 :(得分:2)

  

为什么期待Struct1

因为这是被告知要使用的类型。

给出模板:

template<typename Type>
class GenericClass
{
private:
    Type Identifier;

public:
    void setIdentifier(Type Param);
    Type getIdentifier();
};

类型为Struct1GenericClass<Struct1>)的实例化会生成以下实现:

// Just for illustration
class GenericClassStruct1
{
private:
    Struct1 Identifier;

public:
    void setIdentifier(Struct1 Param);
    Struct1 getIdentifier();
};

上述类已将所有Type替换为Struct1。现在,应该很容易理解为什么调用setIdentifier期望Struct1而不是int

  

如何格式化,以便我可以修改任何结构中的属性

有多种方法可以做到这一点。什么是“正确”的方式将取决于您的问题的限制,但以下示例显示了一种方式。

实施例

Working Example

#include <iostream>

// Declared but not defined, specializations will provide definitions
template<typename T>
struct GenericTypeTraits;

template<typename T>
class Generic
{
public:
    using IdType = typename GenericTypeTraits<T>::IdType;

    void setIdentifier(IdType id)
    {
        mType.mIdentifier = id;
    }

    IdType getIdentifier() const
    {
        return mType.mIdentifier;
    }

private:
    T mType;
};

class Type1
{
public:
    int mIdentifier;
};

template<>
struct GenericTypeTraits<Type1>
{
    using IdType = int;
};

class Type2
{
public:
    std::string mIdentifier;
};

template<>
struct GenericTypeTraits<Type2>
{
    using IdType = std::string;
};

int main()
{
    Generic<Type1> t1[5];
    t1[0].setIdentifier(3);
    std::cout << t1[0].getIdentifier() << "\n";

    Generic<Type2> t2[5];
    t2[0].setIdentifier("3");
    std::cout << t2[0].getIdentifier() << "\n";

    return 0;
}

输出

3
3

答案 1 :(得分:1)

模板GenericClass定义了一系列类。 GenericClass的每个专精都有自己的setIdentifier()专一。因此,GenericClass<Struct1>只有一个setIdentifer()接受Struct1,但没有setIdentifier()接受int(或任何其他类型)。在使用inventory[0].setIdentifier(1)中,inventory[0]的类型为GenericClass<Struct1>,其setIdentifier()成员函数可以接受Struct1但不接受int。因此错误信息。

如果我理解你要做的事情(我不确定 - 只根据你的非工作代码进行猜测)你需要做类似的事情;

template<class T> class Struct
{
   public:
      void SetIdentifier(const T &id) {Identifier = id;};
      T getIdentifier() const {return Identifier;};
    private:
       T Identifier;
       std::string Description;
       float Value;
};

template <class Type>
class GenericClass
{ 
   private:
       Struct<Type> data;
   public:
      void setIdentifier(Type Param) {data.setIdentifier(Param);};
      Type getIdentifier() const {return data.getIdentifier();};
};

int main()
{
      GenericClass<int> inventory[1000];
      inventory[0].setIdentifier(1);
}

答案 2 :(得分:-1)

有问题的方法中的

Identifier是指GenericRecord::Identifier,其中你的一个结构,而不是 成员名为Identifier 。同样,Type是结构类型,而不是其Identifier成员的类型。因此,您的方法永远不会使用您尝试包装的“属性”。

简单的解决方案涉及属性类型的另一个模板参数:

template<class T,class P>
class GenericRecord {
  T wrapped;      // avoid confusing reuse of "Identifier"
public:
  void setIdentifier(P p) {wrapped.Identifier=p;}
  P getIdentifier() const {return wrapped.Identifier;}
};