尾随返回类型的演绎指南不是专业化

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>TN.

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)

不幸的是,这导致类似于这个错误:

error: trailing return type of 'typename ExpandNTimes<T, /* std things */>::Type' deduction guide is not a specialization of ‘Foo<Ts>’
Run Code Online (Sandbox Code Playgroud)

有没有办法解决这个问题?

Bar*_*rry 6

对于类模板参数推导,这是不可能的 - 两个模板名称必须相同,并且后面的东西->必须是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)