如何根据 return 类型编写模板化自由函数

How do write a templated free function depending on return type

我有一个与函数 return 值的类型推导相关的问题。

首先,一些上下文,以显示我的期望。 假设我有这个函数模板:

template <typename T1, typename T2>
T1 foo( T2 t )
{
    T1 a = static_cast<T1>(t); // dummy conversion,
    return a;                  // just there to use t
}

那么,这不构建,因为return类型不能用于类型推导:

int a;
float v1 = foo(a);
char  v2 = foo(a);

但是如果我添加请求的类型,那就没问题了:

int a;
auto v1 = foo<float>(a);
auto v2 = foo<char>(a);

现在是我的问题。我有一个 class,它为某些数据提供 getter:

template<typename T>
struct MyClass
{
   T data;
   template<typename U>
   U get() { return static_cast<U>(data); }  // dummy code, returns an 'U'
};

用户代码可以用这个获取数据(构建良好):

MyClass<int> m;
auto v3 = m.get<float>();

但是我想为用户代码提供第二种访问数据的方式,通过使用一个免费函数,所以可以这样写:

MyClass<int> m;
auto v4 = ff_get<float>(m);

问题是: 如何写ff_get()

我试过了:

template <typename T1, typename T2>
T1 ff_get( T2 t )
{
    return t.get<T1>();
}

但这不会构建,尽管在我看来它使用与上面的 foo 调用相同的语法。所以问题的第二部分是:为什么会失败?

(参见 live code

转换 return 类型而不是推导它

您可以为您的 return 类型创建一个转换代理对象。这会将 return 类型推导改为模板转换操作。

template <typename T>
struct foofoo {
    T t_;
    foofoo (T t) : t_(t) {}
    template <typename U>
    operator U () const { return static_cast<U>(t_); }
};

template <typename T>
foofoo<T> foo( T t )
{
    return foofoo<T>(t);
}

应用于 MyClass,您的 getter 可以类似地实施:

template<typename T>
struct MyClass
{
   T data;
   foofoo<T> get() { return foofoo<T>(data); }
};

然后,这段代码就可以正常工作了:

MyClass<int> m;
float v3 = m.get();

推导出 getter

的 return 类型

现在,要实现 ff_get,它主要是一个简单的函数实现,除了 return 类型现在是从 get 方法本身推导出来的。在 C++11 中,您将使用 trailing return 类型 语法。

template <typename T>
auto ff_get (T t) -> decltype(t.get())
{
    return t.get();
}

从 C++ 14 开始,您可以完全删除尾随 return 类型,因为 return 类型没有歧义。

template <typename T>
auto ff_get (T t)
{
    return t.get();
}