根据模板参数更改参数的 C++ 模板成员函数

c++ template member function that changes parameters depending on template parameter

本文关键字:参数 C++ 成员 函数      更新时间:2023-10-16

>---Edit 以获取更多上下文---

假设我有一个名为TempClass的类。顾名思义,它是一个模板类。它有一堆对这个问题无关紧要的东西,但有趣的东西是一个名为addTo的成员函数和一个作为unordered_map对象的成员变量。让我们称之为inserted.inserted中的所有东西都用addTo放在那里.addTo应该做的是创建一些对象,然后在给定键处将其插入到集合中。插入的实例应在函数内部创建,而不是传递给函数。

addTo(KeyType key, ...) // im looking for what I should put at ...

基本上,我在键后的所有事情上都被困住了。我需要一种方法可以为新创建的实例指定数据,而不必担心对象的生存期或通过调用 std::make_xxx(共享、唯一等)使事情复杂化。

这就是我希望它被称为的方式

TempClass<std::string> stringClass();
stringClass.addTo(whereToAddIt, "This was selected because of std::string");
TempClass<Vector3f> vectorClass();
vectorClass.addTo(someOtherLocation, 12.0f,12.0f,3.0f); //adds a vec(12.0f,12.0f,3.0f)

我已经看到这是这样做的,如果这是一般的良好做法,我喜欢以这种方式实现它。

我尝试过的:

  • 传递指向函数的指针 ------> 有效,但很愚蠢。它需要我注意删除对象
  • 在插入之前传递临时对象并复制它 ------> 有效,但我不喜欢复制对象只是为了删除它。这似乎是多余的,对于我的特定应用程序来说不是最佳的。

我以前见过这个,但我不记得在哪里(相信我,我试图记住这一点,因为如果可以的话,我可以自己查找)。请向我详细解释如何执行此操作以及它是如何工作的。

请帮我弄清楚这一点!

可以使用重载,然后在模板化类型为特定类型时启用特定重载

#include <type_traits> //for enable_if and is_same
template<typename T>
class MyClass
{
public:
template<typename = std::enable_if<std::is_same_v<T, std::string>>>
void someMember(string param1, int param2);
template<typename = std::enable_if<std::is_same_v<T, Vector3f>>>
void someMember(string param1, int param2, int param3);
};

这将选择第一个重载是 T 是 std:string,如果 T 是 Vector3f,则选择第二个重载。

编辑:查看您编辑的问题,更好的方法是将 T 的实例传递给您的 addTo 函数。喜欢:

void addTo(std::string key, T const& value);

编辑2:我想我终于知道你真正想要什么了。您需要使用可变参数模板和完美的转发。这可能看起来令人困惑,所以我会给你代码:

template<typename KeyType, typename... Args>
void addTo(KeyType key, Args&&... args)
{
//now construct the new element with:
T elem(std::forward<Args>(args)...);
}

您将需要包含实用程序标头。有关可变参数模板的更多信息,请参阅 cpp 首选项

您可以使用可变参数模板和完美转发来放置 k/v 对:

template<class K, class V>
struct foo {
template<class... Args>
void addTo(K k, Args&&... args) {
mp.emplace(
std::piecewise_construct, 
std::forward_as_tuple(k),
std::forward_as_tuple(std::forward<Args>(args)...)
);
}
std::unordered_map<K, V> mp;
};