传递指定的模板类型的模板参数
说我有一些模板类型...传递指定的模板类型的模板参数
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>();
感谢您的任何帮助。
此表单模板模板参数只允许在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;
因为它似乎编译为OP,我不认为这个问题。这个问题似乎是如何“修复”模板,以允许一个人写'Foo
@NathanOliver固定,谢谢指向出。 –
太棒了。无论OP需要什么,现在都应该工作。 +1 – NathanOliver
为什么不能简单地用一个标签调度,如:
template <class>
struct tag { };
template <class T>
Foo<T> create(tag<Foo<T>>) {
return Foo<T>(T());
}
//...
Foo<int> foo = create(tag<Foo<int>>{});
这绝对有效,但我正在寻找一个没有功能参数的解决方案。 – Daskie
@Daskie重新考虑你的架构 - 该函数调用将被编译器优化像它不会有任何参数反正... –
在C++ 11
Demo
要点是要有一个名为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
注意,基本模板'create_helper'不需要用'static_assert'死亡。如果你愿意,你可以添加一个'apply'功能就像我们与专业化确实创造T'的'默认实例。 [演示](https://wandbox.org/permlink/bAcedPFMk3I1svmI) – AndyG
一个简单的方法就是在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。
特质和SFINAE似乎是要走的路 – Daskie
所以,实质上,你需要一个'create'函数,它只需要一个'Foo'作为模板类型并返回一个'Foo '? –
NathanOliver
不能简单地是'美孚富= createFoo ();' - 作为构造类型永远是'美孚'呢? –
axalis
@axalis是的,我可以做'createFoo()',而不是'创建>()',但是我正在寻找我可以概括为其他类型的解决方案,例如'创建>' –
Daskie