nyr*_*ium 5 c++ templates c++17
我正在尝试使用来自c ++ 17的新推导指南来进行高级类模板参数推导.不幸的是,看起来你只能在之后使用简单的模板声明->,但我需要一个辅助结构来确定结果类型.
我的用例是这样的:我有一个可变参数模板类,它采用任意数量的不同类型.对于一个构造函数,我想指定每一个,对于另一个ctor,我想只指定一个类型并复制N次.
要N在演绎指南中访问它,我引入了一种新类型:
template<size_t N>
struct Replicate { };
Run Code Online (Sandbox Code Playgroud)
我所拥有的课程与此类似:
template<typename... Foos>
struct Foo {
// [ ... ] member std::tuple<Foos...>
// ctor 1: give values for all types (easy to deduce)
Foo(Foos&&... args /* rvalue ref, NOT forwarding */) { };
// ctor 2: give one value and N, result is N copies of this value.
// takes Replicate<N> as parameter to aid the deduction.
template<typename T, size_t N>
Foo(const T& t, Replicate<N>) { };
};
Run Code Online (Sandbox Code Playgroud)
用法如下:
Foo f1{1, 2, 3.0}; // deduce Foo<int, int, double>;
Foo f2{8, Replicate<4>{}}; // deduce Foo<int, int, int, int>;
Run Code Online (Sandbox Code Playgroud)
第一个的演绎指南是直截了当的:
template<typename... Ts>
Foo(Ts&&...) -> Foo<Ts...>;
Run Code Online (Sandbox Code Playgroud)
第二个(ctor 2)演绎指南会出现问题.首先,我需要一个辅助结构来创建Foo<T, T, ... /* total N times */, T>自T和N.
template<typename, typename, typename>
struct ExpandNTimes;
template<typename T, size_t... Is>
struct ExpandNTimes<T, std::index_sequence<Is...>> {
template<size_t> using NthType = T;
using Type = Foo<NthType<Is>...>;
};
Run Code Online (Sandbox Code Playgroud)
然后在演绎指南中,我想利用帮助器推断出正确的类型.我不能直接使用,Foo<something>因为没有任何"就地参数包创建",因此辅助结构.
template<typename T, size_t N>
Foo(const T&, Replicate<N>) -> typename ExpandNTimes<T, std::make_index_sequence<N>>::Type;
Run Code Online (Sandbox Code Playgroud)
不幸的是,这导致类似于这个错误:
Run Code Online (Sandbox Code Playgroud)error: trailing return type of 'typename ExpandNTimes<T, /* std things */>::Type' deduction guide is not a specialization of ‘Foo<Ts>’
有没有办法解决这个问题?
对于类模板参数推导,这是不可能的 - 两个模板名称必须相同,并且后面的东西->必须是simple-template-id.这并没有给模板恶作剧留下任何空间.
但没有什么可以阻止你做类模板参数推导意图取代的东西:工厂函数:
template <typename T, size_t N>
typename ExpandNTimes<T, std::make_index_sequence<N>>::Type
makeFoo(T const&, Repliace<N>);
Run Code Online (Sandbox Code Playgroud)