【问题标题】:C++ variable that holds any specialization of class template包含类模板的任何特化的 C++ 变量
【发布时间】:2016-04-25 16:28:53
【问题描述】:

我需要能够将模板的任何特化存储在变量中,例如:

template<T>
class Grid {
  int GetRows();
  int GetTypeOfColumn(int col);
  //...etc...
}

//EDIT:
Grid<int>::GetTypeofColumn(int col) {
   return col == 0 ? STRING_COL_TYPE : INT_COL_TYPE;
}
Grid<string>::GetTypeofColumn(int col) {
   return STRING_COL_TYPE;
}
//End EDIT

class Foo {
  Grid<int>* aBunchOfNumbers;
  Grid<string>* aBunchOfStrings;
  //...etc...
}

//in some function, say `wants` is an enum, and foo is gotten from somewhere:
Foo* foo; 
switch wants {
  case NUMBERS:
    std::cout << "Rows: " << foo->aBunchOfNumbers->GetRows() << std::endl;
    std::cout << "Col0 is: " << foo->aBunchOfNumbers->GetTypeofColumn(0) << std::endl;
    //...etc...
    break;
  case STRINGS:
    std::cout << "Rows: " << foo->aBunchOfNumbers->GetRows() << std::endl;
    std::cout << "Col0 is: " << foo->aBunchOfNumbers->GetTypeofColumn(0) << std::endl;
    //...etc...
    break;
}

这样做会更容易:

Foo* foo;
Grid* grid;
switch wants {
  case NUMBERS:
    grid = foo->aBunchOfNumbers;
    break;
  case STRINGS:
    grid = foo->aBunchOfStrings;
    break;
}
std::cout << "Rows: " << grid->GetRows() << std::endl;
std::cout << "Col0 is: " << grid->GetTypeofColumn(0) << std::endl;
//...etc...

如果我使用这样的子类,同样的方式:http://ideone.com/MPKy1w

我知道类模板几乎基本上是宏以及编译器如何实际编译它们,但有没有办法泛指特化并节省重复?

(这里特意用了指针,我的实际代码没有选择,这里不能复制)

【问题讨论】:

  • 你想要一些多态性。有静态(重载、模板)和动态(虚拟函数)。随便选一个。
  • 但是有了多态性,他不是必须为他想要包含的每个新类定义一个派生类吗?
  • @Stephen 没有模板
  • 但是 GetTypeOfColumn 的实现取决于模板中的 T 类型?
  • @Stephen 如果模板本身是从多态基派生的,则不是。

标签: c++ templates template-meta-programming template-specialization


【解决方案1】:

使用所需的方法(“接口”)创建类。这样做是可能的,因为您的方法不依赖于模板参数T

class GridOperations {
    virtual int GetRows() = 0;
    virtual int getTypeOfColumn(int col) = 0;
    virtual ~GridOperations() {}
};

现在从上面的类继承 Grid:

template<T>
class Grid : public GridOperations {
  int GetRows() { /* impl */ }
  int GetTypeOfColumn(int col) { /* impl */ }
};

现在您可以将Grid&lt;int&gt;*Grid&lt;string&gt;* 都转换为GridOperations*

Foo* foo;
GridOperations* ops;
switch wants {
  case NUMBERS:
    ops = foo->aBunchOfNumbers;
    break;
  case STRINGS:
    ops = foo->aBunchOfStrings;
    break;
}
std::cout << "Rows: " << ops->GetRows() << std::endl;
std::cout << "Col0 is: " << ops->GetTypeofColumn(0) << std::endl;

奖励:你甚至可以使用std::map&lt;WantEnumType, GridOperations*&gt; 来避免讨厌的开关阻塞。

【讨论】:

  • 谢谢,如果一个方法有一个类型为 T 的参数,例如。 GetValue(T* obj),在一个也采用类型 T 的函数中调用? pastebin.com/BqTNQ8iD
  • 在这种情况下,您将someMemberFunction 也声明为函数模板:http://pastebin.com/RwSqxitR。想法是,如果您的类/功能取决于smth。模板化,那么它(类/函数)也必须被模板化。您还必须了解Grid&lt;string&gt;Grid&lt;int&gt; 从编译器的角度来看是两个不同的类(如Robot、PricingPolicy 和GreenException)。模板是创建类似函数和类的以避免单独编写它们的方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-22
相关资源
最近更新 更多