我有一个template<typename T> class Foo。
我想声明一个函数,它可以返回任何类型的Foo。我会这样做:template<typename T> Foo<T> bar();
但这意味着我必须像这样使用它:Foo<SomeConcreteT> f = bar<SomeConcreteT>();和SomeConcreteT可以非常长、笨重、烦人而不得不打印出来。
但是,我确实有一些
using AppleFoo = Foo<ABunchOfStuffForApples>;
using BananaFoo = Foo<SomethingElseForBananas>;
// ...我更喜欢这样调用bar:AppleFoo f = bar<AppleFoo>();,这样我就不必一直键入ABunchOfStuffForApples,从概念上讲,AppleFoo比ABunchOfStuffForApples更多地告诉读者应该发生什么。
我可以通过在using TType = T中添加Foo和类似于以下的助手函数来实现这一点:
template<typename F>
F bar()
{
return bar<F::TType>();
}但是这是丑陋和容易出错的(例如调用bar<SomethingThatIsNotAFoo>())。
有更干净的方法吗?
是否有一种更一般的方法来测试某些类型是否是SomethingKnown<SomethingUnknown>,例如在static_assert中
发布于 2022-02-14 10:10:50
您可以假装有返回类型的扣减,方法是让bar是一个非模板,返回带有operator Foo<T>的代理。
template <typename T>
struct Foo {
/* ... */
};
namespace detail {
struct bar_t {
template <typename T>
operator Foo<T>() { /* current implemenation of bar */ }
};
}
detail::bar_t bar() { return {}; }
using AppleFoo = Foo<struct Apple>;
int main() {
AppleFoo f = bar();
}发布于 2022-02-14 10:22:13
您可以创建一个特征来知道它是否是Foo,并提取其模板参数:
template <typename T>
struct is_foo : std::false_type {};
template <typename T>
struct is_foo<Foo<T>> : std::true_type
{
using type = T;
};然后
template<typename FOO>
FOO bar()
{
static_assert(is_foo<FOO>::value);
using T = typename is_foo<FOO>::type;
// ...
}发布于 2022-02-14 12:33:22
作为替代,如果您可以更改调用语法,则可以传递一个标记,
template <typename T> struct tag {};然后
template<typename T>
Foo<T> bar(tag<Foo<T>>)
{
return bar<T>();
}的用法类似于
using AppleFoo = Foo<ABunchOfStuffForApples>;
auto bar1 = bar(tag<AppleFoo>{});
auto bar2 = bar(tag<Foo<ABunchOfStuffForApples>>{});
// auto is AppleFoo and so Foo<ABunchOfStuffForApples>如果不喜欢接口中的标记,仍然可以将其用作实现:
template<typename T>
Foo<T> bar_impl(tag<Foo<T>>)
{
// implementation, such as return Foo<T>();
}
// Possibly other specialization for Foo<std::vector<T>>, Foo<int>, ..
template<typename T>
auto bar()
{
return bar_impl(tag<T>{});
}与使用
using AppleFoo = Foo<ABunchOfStuffForApples>;
auto bar1 = bar<AppleFoo>();
auto bar2 = bar<Foo<ABunchOfStuffForApples>>();
// auto is AppleFoo and so Foo<ABunchOfStuffForApples>https://stackoverflow.com/questions/71110004
复制相似问题