重载模板化函数,根据模板参数具有不同的返回类型

Overloading templated function, with different return types based on template parameter

本文关键字:返回类型 函数 重载 参数      更新时间:2023-10-16

我有一个接受参数的函数。有时它是一个"原始"数字,有时它是一个包装在持有者类中的数字,其中包含有关该数字的一些元信息。我可以像这样区分这两种情况

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

这是否可以在不更改函数名称的情况下进行?(如果没有,没什么大不了的,我只是好奇)

除了使用

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(); }

这两种方法都可能或多或少清楚,它们都应该有效。

是的,这是可能的,使用 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>
}

当然,在调用模板参数时,您仍然必须显式指定它。

Checkout decltype。

    template <class T, class U>
    auto add(T t, U u) -> decltype(t + u);