我正在尝试编写一个返回给定类型向量的函数。如果我只使用浮点数和整数的向量作为我的返回类型,一切正常,但如果我尝试返回结构的向量,我会得到一个错误,表明float或int不能转换为结构的类型名称。我该如何解决这个问题。我已经列举了一个我正在尝试做的事情的例子。提前谢谢!
#include <cstdlib>
#include <vector>
using namespace std;
struct test
{
static const int x = 10;
};
template<class T>
vector<T> doStuff(T input, int IT)
{
if (IT == 1)
{
vector<T> result(10);
for(int i = 0; i < 10; i++)
result[i] = 0.1*i;
return result;
}
else if (IT == 2)
{
vector<T> result(10);
for(int i = 0; i < 10; i++)
result[i] = i;
return result;
}
else if (IT == 3)
{
test t;
vector<T> result(10);
for(int i = 0; i < 10 ;i++)
result[i] = t;
return result;
}
}
int main(int argc, char** argv) {
float input1 = 0.0;
vector<float> result1 = doStuff(input1, 1);
int input2 = 0;
vector<int> result2 = doStuff(input2,2);
test input3;
vector<test> result3 = doStuff(input3,3);
return 0;
}
答案 0 :(得分:3)
您缺少的是整个函数必须编译,甚至是if (IT == 1)
内部将浮点值赋给vector<T>
的部分。这部分导致了你的问题。
看起来你正在尝试创建某种算法,但我无法从你的问题中推断出你正在尝试做些什么来为你的真正问题提供解决方案。
答案 1 :(得分:1)
您对模板的工作方式存在误解。调用函数模板或&#34;实例化&#34;时,必须知道模板参数。在您的情况下,模板参数T
是从doStuff
的第一个参数推导出来的。当模板参数已知时,它允许生成新函数。第一次调用doStuff
(doStuff(input1, 1)
)会生成如下函数:
vector<float> doStuff(float input, int IT);
基本上发生的是T
被推断的类型(即float
)替换。你能看出这是怎么回事吗?由于T
被float
替换,编译器会看到如下无效代码:
test t;
vector<float> result(10);
for (int i = 0; i < 10 ;i++)
result[i] = t;
return result;
您已将float
变量(result[i]
)分配给test
数据类型。这两种类型不兼容,会导致错误。
使用IT
参数来&#34;了解一下&#34;传递的类型也是不正确的。如果您的函数根据类型具有不同的行为,则可以使用overloading或函数模板专门化。我建议重载。
答案 2 :(得分:0)
您可以通过使IT
也成为模板参数并使用帮助程序类来完成核心工作来实现这一目标。
#include <cstdlib>
#include <vector>
using namespace std;
struct test
{
static const int x = 10;
};
template <int IT> struct DoStuffHelper;
template <> struct DoStuffHelper<1>
{
typedef std::vector<int> ReturnType;
template <class T>
static ReturnType get(T input)
{
ReturnType result(10);
for(int i = 0; i < 10; i++)
result[i] = 0.1*i;
return result;
}
};
template <> struct DoStuffHelper<2>
{
typedef std::vector<float> ReturnType;
template <class T>
static ReturnType get(T input)
{
ReturnType result(10);
for(int i = 0; i < 10; i++)
result[i] = 0.1*i;
return result;
}
};
template <> struct DoStuffHelper<3>
{
typedef std::vector<test> ReturnType;
template <class T>
static ReturnType get(T input)
{
test t;
ReturnType result(10);
for(int i = 0; i < 10 ;i++)
result[i] = t;
return result;
}
};
template <int IT, class T>
typename DoStuffHelper<IT>::ReturnType doStuff(T input)
{
return DoStuffHelper<IT>::get(input);
}
int main(int argc, char** argv) {
float input1 = 0.0;
vector<int> result1 = doStuff<1>(input1);
int input2 = 0;
vector<float> result2 = doStuff<2>(input2);
test input3;
vector<test> result3 = doStuff<3>(input3);
return 0;
}
答案 3 :(得分:0)
创建一个模板函数,根据它的实例化方式返回不同的类型很容易。
真正的问题是,你在这里尝试创建一个完全不同的模板函数,具体取决于它是如何实例化的,并且你尝试对该类型采取的某些类型和操作组合显然是不允许的
如果您只想返回与传入的相同类型(或某些派生类型,例如传递给T时的向量),您可以很容易地执行此操作:
template <class T>
std::vector<T> make10(T const &val) {
std::vector<T> ret;
for (int i=0; i<10; i++)
ret.push_back(val);
return ret;
}
现在,您可以执行以下操作:
std::vector<double> x = make10(1.0);
std::vector<int> y = make10(1);
test t;
std::vector<test> z = make10(t);
虽然可以创建多个具有相同名称的函数,这些函数根据类型(使用重载或特化)执行不同的操作,但通常应该避免这样做。重载和特化应该用于实现仍然基本上做同样事情的函数,但是以不同的方式完成它们。
但是,至少在大多数情况下,当您处理重载函数时,您应该能够对它们所做的事情给出完全相同的描述。如果一个是“输入N个副本”而另一个是“输入的N个副本除以10”,第三个是“制作一个默认构造对象的n个副本”,那么你通常应该看三个具有三个独立名称的单独函数,而不是具有相同名称的同一函数的重载或特化。