如何使用模板选择类成员

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

How to select a class member using templates

问题

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

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

英文:

Consider the example code below.

#include <iostream>

enum class FruitType {
    APPLE,
    ORANGE
};

class Fruit {
    uint64_t apple_count;
    uint64_t orange_count;

public:
    Fruit() : apple_count(0), orange_count(0) {}
    void increase_count(FruitType type) {
        if (type == FruitType::APPLE)
            apple_count++;
        else
            orange_count++;
    }
    void print() {
        std::cout << "apple_count: " << apple_count << std::endl;
        std::cout << "orange_count: " << orange_count << std::endl;
    }
};

int main(int, char**) {
    Fruit fruit;
    fruit.increase_count(FruitType::APPLE);
    fruit.increase_count(FruitType::ORANGE);
    fruit.increase_count(FruitType::APPLE);
    fruit.increase_count(FruitType::APPLE);
    fruit.increase_count(FruitType::ORANGE);
    fruit.print();

    return 0;
}

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 设为一个接受非类型模板参数的模板,你可以做到:

class Fruit {
	uint64_t apple_count;
	uint64_t orange_count;

public:
	Fruit() : apple_count(0), orange_count(0) {}
	template <FruitType type>
	void increase_count() {
		if constexpr (type == FruitType::APPLE)
			apple_count++;
		else
			orange_count++;
	}
	void print() {
		std::cout << "apple_count: " << apple_count << std::endl;
		std::cout << "orange_count: " << orange_count << std::endl;
	}
};

int main(int, char**) {
	Fruit fruit;
	fruit.increase_count<FruitType::APPLE>();
	fruit.increase_count<FruitType::ORANGE>();
	fruit.increase_count<FruitType::APPLE>();
	fruit.increase_count<FruitType::APPLE>();
	fruit.increase_count<FruitType::ORANGE>();
	fruit.print();

	return 0;
}

这将在编译时移除分支,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

class Fruit {
	uint64_t apple_count;
	uint64_t orange_count;

public:
	Fruit() : apple_count(0), orange_count(0) {}
	template &lt;FruitType type&gt;
	void increase_count() {
		if constexpr (type == FruitType::APPLE)
			apple_count++;
		else
			orange_count++;
	}
	void print() {
		std::cout &lt;&lt; &quot;apple_count: &quot; &lt;&lt; apple_count &lt;&lt; std::endl;
		std::cout &lt;&lt; &quot;orange_count: &quot; &lt;&lt; orange_count &lt;&lt; std::endl;
	}
};

int main(int, char**) {
	Fruit fruit;
	fruit.increase_count&lt;FruitType::APPLE&gt;();
	fruit.increase_count&lt;FruitType::ORANGE&gt;();
	fruit.increase_count&lt;FruitType::APPLE&gt;();
	fruit.increase_count&lt;FruitType::APPLE&gt;();
	fruit.increase_count&lt;FruitType::ORANGE&gt;();
	fruit.print();

	return 0;
}

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:

确定