如何根据 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();
}
我有一个与函数 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();
}