我有一个带参数的函数。有时它是一个“原始”数字,有时它是一个包含在持有者类中的数字,其中包含一些关于数字的元信息。我可以区分这两种情况
template<class T>
struct Holder
{
};
template<class T>
void f1(T)
{
}
template<class T>
void f1(Holder<T>)
{
}
但是,现在我想根据用户的需要返回原始数字或持有者。我知道用户在调用函数时必须显式指定模板参数。这没关系,但如果可能的话,我希望函数具有相同的名称。像这样的东西
template<class T>
T f1()
{
return T();
}
template<class T>
Holder<T> f1()
{
return T();
}
但是,将其称为f1<int>();
或f1<Holder<int>>();
会导致error: ambiguous call to overloaded function
这是否可以在不更改功能名称的情况下进行? (如果没有,这不是什么大问题,我只是好奇)
答案 0 :(得分:3)
除了使用SFINAE(std::enable_if
)的方法之外,您还可以使用部分特化。由于功能模板无法实现部分特化,因此需要稍微跳过箍,但是:
template <typename T>
struct f1_specialization {
static T f1() { ... }
};
template <typename T>
struct f1_specialization<Holder<T>> {
static Holder<T> f1() { ... }
};
template <typename T>
T f1() { return f1_specialization<T>::f1(); }
任何一种方法都可能或多或少都清楚,它们都应该起作用。
答案 1 :(得分:1)
是的,可以使用enable_if
。但它太可怕了。我将用C ++ 11编写这个。
template <typename T> struct is_holder {
static constexpr bool value = false;
};
template <typename T> struct is_holder<Holder<T>> {
static constexpr bool value = true;
};
template <typename T,
typename = typename std::enable_if<is_holder<T>::value>::type>
T f1() {
// T is Holder<U>
}
template <typename T,
typename = typename std::enable_if<!is_holder<T>::value>::type>
T f1() {
// T is not Holder<U>
}
当然,当你调用模板参数时,仍然必须明确指定模板参数。
答案 2 :(得分:0)
结帐decltype。
template <class T, class U>
auto add(T t, U u) -> decltype(t + u);