如何使用模板选择类成员

huangapple go评论114阅读模式
英文:

How to select a class member using templates

问题

我想将 increase_count 函数有效地编译成 increase_count_appleincrease_count_orange。这是另一个类的简化示例,其中这种编译时优化在理论上可以帮助我在运行时。直观地感觉可以使用模板来实现,但我无法得出令人满意的结果。

请注意,这是您要求的代码部分的翻译。

英文:

Consider the example code below.

  1. #include <iostream>
  2. enum class FruitType {
  3. APPLE,
  4. ORANGE
  5. };
  6. class Fruit {
  7. uint64_t apple_count;
  8. uint64_t orange_count;
  9. public:
  10. Fruit() : apple_count(0), orange_count(0) {}
  11. void increase_count(FruitType type) {
  12. if (type == FruitType::APPLE)
  13. apple_count++;
  14. else
  15. orange_count++;
  16. }
  17. void print() {
  18. std::cout << "apple_count: " << apple_count << std::endl;
  19. std::cout << "orange_count: " << orange_count << std::endl;
  20. }
  21. };
  22. int main(int, char**) {
  23. Fruit fruit;
  24. fruit.increase_count(FruitType::APPLE);
  25. fruit.increase_count(FruitType::ORANGE);
  26. fruit.increase_count(FruitType::APPLE);
  27. fruit.increase_count(FruitType::APPLE);
  28. fruit.increase_count(FruitType::ORANGE);
  29. fruit.print();
  30. return 0;
  31. }

I want the increase_count function to effectively compile to increase_count_apple and increase_count_orange. This is a simplified example of another class where such compile-time optimisation helps me at runtime, in theory. Intuitively, this feels possible using templates, but I am unable to arrive at a satisfactory output.

答案1

得分: 4

通过将 increase_count 设为一个接受非类型模板参数的模板,你可以做到:

  1. class Fruit {
  2. uint64_t apple_count;
  3. uint64_t orange_count;
  4. public:
  5. Fruit() : apple_count(0), orange_count(0) {}
  6. template <FruitType type>
  7. void increase_count() {
  8. if constexpr (type == FruitType::APPLE)
  9. apple_count++;
  10. else
  11. orange_count++;
  12. }
  13. void print() {
  14. std::cout << "apple_count: " << apple_count << std::endl;
  15. std::cout << "orange_count: " << orange_count << std::endl;
  16. }
  17. };
  18. int main(int, char**) {
  19. Fruit fruit;
  20. fruit.increase_count<FruitType::APPLE>();
  21. fruit.increase_count<FruitType::ORANGE>();
  22. fruit.increase_count<FruitType::APPLE>();
  23. fruit.increase_count<FruitType::APPLE>();
  24. fruit.increase_count<FruitType::ORANGE>();
  25. fruit.print();
  26. return 0;
  27. }

这将在编译时移除分支,fruit.increase_count<FruitType::APPLE> 实际上调用 increase_count_applefruit.increase_count<FruitType::ORANGE>() 调用 increase_count_orange

英文:

By making increase_count a template that takes a non-type template paramter you can do

  1. class Fruit {
  2. uint64_t apple_count;
  3. uint64_t orange_count;
  4. public:
  5. Fruit() : apple_count(0), orange_count(0) {}
  6. template &lt;FruitType type&gt;
  7. void increase_count() {
  8. if constexpr (type == FruitType::APPLE)
  9. apple_count++;
  10. else
  11. orange_count++;
  12. }
  13. void print() {
  14. std::cout &lt;&lt; &quot;apple_count: &quot; &lt;&lt; apple_count &lt;&lt; std::endl;
  15. std::cout &lt;&lt; &quot;orange_count: &quot; &lt;&lt; orange_count &lt;&lt; std::endl;
  16. }
  17. };
  18. int main(int, char**) {
  19. Fruit fruit;
  20. fruit.increase_count&lt;FruitType::APPLE&gt;();
  21. fruit.increase_count&lt;FruitType::ORANGE&gt;();
  22. fruit.increase_count&lt;FruitType::APPLE&gt;();
  23. fruit.increase_count&lt;FruitType::APPLE&gt;();
  24. fruit.increase_count&lt;FruitType::ORANGE&gt;();
  25. fruit.print();
  26. return 0;
  27. }

which removes the branch at compile time and fruit.increase_count&lt;FruitType::APPLE&gt; effectively calls increase_count_apple and fruit.increase_count&lt;FruitType::ORANGE&gt;() calls increase_count_orange.

huangapple
  • 本文由 发表于 2023年6月5日 20:54:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/76406626.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定