请考虑以下示例:
#include <string>
#include <vector>
using std::string;
using std::vector;
template <typename T>
const T GetValue()
{
return T(); // some value
}
template <typename T>
const vector<T> GetValue()
{
return vector<T>(); // some vector of values
}
int main(int argc, char* argv[])
{
int i = GetValue<int>();
vector<int> = GetValue<vector<int>>();
return 0;
}
我有两个模板函数,它们应该根据给定的类型解析某些存储中的值。第一个应该完成简单数据类型的工作,第二个应该只用于简单数据类型的向量。
我的问题是模板匹配不明确,因为T
可能是vector<T>
。
我想知道如何正确地实现矢量类型的重载/特化。
非常感谢任何帮助!
答案 0 :(得分:6)
一种简单的方法是使用out-param,以便可以从参数中推导出模板参数:
#include <vector>
using std::vector;
template <typename T>
void GetValue(T &t)
{
t = T(); // some value
}
template <typename T>
void GetValue(vector<T> &v)
{
v = vector<T>(); // some vector of values
}
int main(int argc, char* argv[])
{
int i;
GetValue(i);
vector<int> v;
GetValue(v);
return 0;
}
GetValue(v)
不明确,因为模板参数推导规则说第二次重载是更好的匹配。
这不一定是您想要的界面/样式,但在这种情况下,您可以使用部分特化而不是重载。但这需要一个类,因为函数模板不能部分专门化:
#include <vector>
using std::vector;
template <typename T>
struct Getter {
T get(void) {
return T(); // some value
}
};
template <typename T>
struct Getter<vector<T> > {
vector<T> get(void) {
return vector<T>(); // some vector of values
}
};
template <typename T>
T GetValue(void)
{
return Getter<T>().get();
}
int main(int argc, char* argv[])
{
int i = GetValue<int>();
vector<int> v = GetValue<vector<int> >();
return 0;
}
答案 1 :(得分:4)
GetValue
的两个版本仅因返回类型而不同,因此它不会过载。
我建议你只有一个GetValue
,然后实现两个不同于参数类型的函数,而不是 return 类型,并转发打电话给:
namespace details
{
template <typename T>
T FillValue(T*)
{
//your code
}
template <typename T>
vector<T> FillValue(vector<T> *)
{
//your code
}
}
template <typename T>
T GetValue()
{
return details::FillValue((T*)0); //pass null pointer of type T*
}
编译器将根据传递给函数的参数的类型选择正确的FillValue
,即T*
。如果某个类型T
的{{1}}为vector<U>
,则会选择第二个函数,否则将选择第一个函数。
答案 2 :(得分:1)
您可以将部分特化移动到辅助类:
#include <vector>
template <typename T>
class Creator {
public:
T operator()() const { return T(); }
};
template <typename T>
class Creator<std::vector<T> > {
public:
std::vector<T> operator()() const { return std::vector<T>(); }
};
template <typename T>
T GetValue() {
return Creator<T>()();
}
int main() {
int i = GetValue<int>();
std::vector<char> v = GetValue<std::vector<char> >();
}
答案 3 :(得分:1)
将一般方法放在class
(最好命名为GetValue
)中,并将该方法声明为operator T()
。现在专注class
的{{1}}:
vector<T>
用法:
template <typename T>
struct GetValue
{
operator const T () const
{
std::cout<<"GetValue()\n";
return T(); // some value
}
};
template <typename T>
struct GetValue<vector<T> >
{
operator const vector<T> ()
{
std::cout<<"GetValue<vector<T>>()\n";
return vector<T>(); // some vector of values
}
};