说我有一些模板类型......
template <typename T> struct Foo {
Foo(T t) {}
};
有没有办法将指定的Foo类型传递给函数,以便函数可以直接看到T?
理想情况下,我可以写这样的东西......
Foo<int> foo = create<Foo<int>>();
我最接近的是
template <
template <typename> typename TT,
typename T,
std::enable_if_t<std::is_same<TT<T>, Foo<T>>::value, int> = 0
>
Foo<T> create() {
return Foo<T>(T());
}
然后将像
一样使用Foo<int> foo = create<Foo, int>();
感谢您的帮助。
答案 0 :(得分:6)
这种形式的模板模板参数仅允许在C ++ 17中使用:
template < // v---------- typename here not allowed
template <typename> typename TT,
typename T,
std::enable_if_t<std::is_same<TT<T>, Foo<T>>::value, int> = 0
>
Foo<T> create() {
return Foo<T>(T());
}
您必须替换typename
指出的class
:
template < // v---------- class allowed
template <typename> class TT,
typename T,
std::enable_if_t<std::is_same<TT<T>, Foo<T>>::value, int> = 0
>
Foo<T> create() {
return Foo<T>(T());
}
在C ++ 17中,两者都编译并且是等效的。
要使语法Foo<int> foo = create<Foo<int>>();
正常工作,您只需执行此操作:
template <typename T>
T create() {
return T{};
}
如果要限制可以发送的类型,则必须创建类型特征:
// default case has no typedef
template<typename>
struct first_param {};
// when a template is sent, define the typedef `type` to be equal to T
template<template<typename> class TT, typename T>
struct first_param<TT<T>> {
using type = T;
};
// template alias to omit `typename` everywhere we want to use the trait.
template<typename T>
using first_param_t = typename first_param<T>::type;
然后,使用你的特质:
template <
typename T,
void_t<first_param_t<T>>* = nullptr
> // ^---- if the typedef is not defined, it's a subtitution error.
T create() {
return T(first_param_t<T>{});
}
您可以像这样实施void_t
:
template<typename...>
using void_t = void;
答案 1 :(得分:4)
为什么不简单地使用标签调度,例如:
function_b()
答案 2 :(得分:4)
一种简单的方法是直接在Foo
中添加子类型信息:
template <typename T> struct Foo {
using type = T;
Foo(T t) {}
};
然后
template <typename FooT>
FooT create() {
return FooT(typename FooT::type{});
}
如果需要,您可以添加SFINAE:
template <typename FooT>
auto create()
-> decltype(FooT(typename FooT::type{}))
{
return FooT(typename FooT::type{});
}
如果你想真正将函数限制为Foo
,你必须在其上创建一个特征和SFINAE。
答案 3 :(得分:2)
在C ++ 11中
要点是要有一个名为create
的入口点函数,它可以实例化create_helper
结构以创建正确的类型。
我们可以使用模板特化来创建我们的结构,以便我们强制传递模板化的类。
template<class T>
struct create_helper
{
static_assert(sizeof(T) == 0, "Need to pass templated type to create");
};
template <class T, template<class> class TT>
struct create_helper<TT<T>>
{
static TT<T> apply()
{
return {T{}};
}
};
template<class T>
auto create() -> decltype(create_helper<T>::apply())
{
return create_helper<T>::apply();
}
测试:
template<class T>
struct Foo
{
Foo(T t){std::cout << "Constructed Foo with value " << t << std::endl;}
};
int main()
{
Foo<int> foo = create<Foo<int>>();
}
输出:
Constructed Foo with value 0