简体   繁体   English

在 C++ 中的模板实例化中使用带有构造函数的类作为类型参数

[英]Using a class with a constructor as a type parameter in a template instantiation in c++

In C++ (14) I have a template class with a type T for which I would like to use a class as the type.在 C++ (14) 中,我有一个类型为 T 的模板类,我想使用一个类作为类型。 The class that I want to use for the type requires a parameter in its constructor... so how do I pass this parameter through the template instantiation?我想用于该类型的类在其构造函数中需要一个参数......那么我如何通过模板实例化传递这个参数?

My example code (template_hell.cpp):我的示例代码(template_hell.cpp):

#include <iostream>

template <typename T>
class my_template
{
public:
  struct Stored_Data_Type
  {
    T data;
    int set_count = 0;
  };

  my_template() : m_data() {};

  T& write()
  {
    m_data.set_count++;
    return m_data.data;
  }

  const T& get() const {return m_data.data;}

private:
  Stored_Data_Type m_data;
};

class a_class
{
public:

  a_class(int init): m_data(init) {};

  void set(const int data) {m_data = data;};

  const int get() const {return m_data;};

private:
  int m_data;
};

class b_class : public a_class
{
public:
  b_class(): a_class{0} {};
};

int main()
{
  //a_class b(1);
  b_class b;
  b.set(2);
  std::cout << "b: " << b.get() << std::endl;

  my_template<int> my_int;
  my_int.write() = 10;
  std::cout << "my_int: " << my_int.get() << std::endl;

  my_template<b_class> my_b;
  my_b.write().set(2);
  std::cout << "my_b: " << my_b.get().get() << std::endl;

  // Compile error here:
  my_template<a_class> my_a;
  my_a.write().set(3);
  std::cout << "my_a: " << my_a.get().get() << std::endl;
}

This all works and is fine until I add in the my_a template instance.在我添加my_a模板实例之前,这一切正常并且很好。 Then I get this compile error:然后我得到这个编译错误:

template_hell.cpp: In instantiation of 'my_template<T>::my_template() [with T = a_class]':
template_hell.cpp:62:24:   required from here
template_hell.cpp:13:26: error: use of deleted function 'my_template<a_class>::Stored_Data_Type::Stored_Data_Type()'
   my_template() : m_data() {};
                          ^
template_hell.cpp:7:10: note: 'my_template<a_class>::Stored_Data_Type::Stored_Data_Type()' is implicitly deleted because the default definition would be ill-formed:
   struct Stored_Data_Type
          ^~~~~~~~~~~~~~~~
template_hell.cpp:7:10: error: no matching function for call to 'a_class::a_class()'
template_hell.cpp:31:3: note: candidate: a_class::a_class(int)
   a_class(int init): m_data(init) {};
   ^~~~~~~
template_hell.cpp:31:3: note:   candidate expects 1 argument, 0 provided
template_hell.cpp:27:7: note: candidate: constexpr a_class::a_class(const a_class&)
 class a_class
       ^~~~~~~
template_hell.cpp:27:7: note:   candidate expects 1 argument, 0 provided
template_hell.cpp:27:7: note: candidate: constexpr a_class::a_class(a_class&&)
template_hell.cpp:27:7: note:   candidate expects 1 argument, 0 provided

How do I pass the parameter to a_class through the template instance?如何通过模板实例将参数传递给 a_class? Is this not possible?这不可能吗?

You are passing a_class as a template parameter to the my_template template class and, since inside my_template class Stored_Data_Type m_data;您将a_class作为模板参数传递给my_template模板类,并且由于在my_template类中Stored_Data_Type m_data; is an object of following struct是以下struct的对象

struct Stored_Data_Type {
    a_class data;
    int set_count = 0;
};

m_data member is default constructed with m_data成员默认构造为

my_template() : m_data() {}

which tries to call a_class 's default constructor which you haven't defined.它试图调用您尚未定义的a_class的默认构造函数。

Therefore, you just need to define default constructor for your a_class class:因此,您只需要为a_class类定义默认构造函数:

class a_class {
public:
    a_class()
        : m_data{0}
    {}

    // ...
};

Check live example检查实时示例

You could make use of Variadic arguments.您可以使用 Variadic 参数。 See https://en.cppreference.com/w/cpp/language/parameter_pack .请参阅https://en.cppreference.com/w/cpp/language/parameter_pack This allows us to forward on any arguments to the StoredDataType that are passed to our my_template class这让我们对任何参数的转发StoredDataType传递给我们的my_template

Variadic templates allow us to write classes/methods that take an arbitrary number of arguments in a type-safe way and have all the argument handling logic resolved at compile-time, rather than run-time可变模板允许我们以类型安全的方式编写接受任意数量参数的类/方法,并在编译时而不是运行时解决所有参数处理逻辑

#include <iostream>

template <typename T>
class my_template
{
public:
  struct Stored_Data_Type
  {
      template<typename... TArgs>
      Stored_Data_Type(TArgs&&... args) : data(std::forward<TArgs>(args)...)
      {

      }

    T data;
    int set_count = 0;
  };

  template<typename... TArgs>
  my_template(TArgs&&... args) : m_data(std::forward<TArgs>(args)...) {}

  T& write()
  {
    m_data.set_count++;
    return m_data.data;
  }

  const T& get() const {return m_data.data;}

private:
  Stored_Data_Type m_data;
};

class a_class
{
public:

  a_class(int init): m_data(init) {};

  void set(const int data) {m_data = data;};

  const int get() const {return m_data;};

private:
  int m_data;
};

class b_class : public a_class
{
public:
  b_class(): a_class{0} {};
};

int main()
{
  //a_class b(1);
  b_class b;
  b.set(2);
  std::cout << "b: " << b.get() << std::endl;

  my_template<int> my_int;
  my_int.write() = 10;
  std::cout << "my_int: " << my_int.get() << std::endl;

  my_template<b_class> my_b;
  my_b.write().set(2);
  std::cout << "my_b: " << my_b.get().get() << std::endl;

  // Compile error here:
  my_template<a_class> my_a(1);
  std::cout << "my_a: " << my_a.get().get() << std::endl;
}

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

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