我写了一些可以在最新版本的GCC和Clang上很好地编译的代码,但是在MSVC上失败了:

谁能解释一下这是一个错误还是我误解了?
没有types_list的部分特化,它在MSVC上也可以正常工作。

#include <cstdint>
#include <type_traits>

namespace detail
{
    template <std::size_t Index, typename ...Ts>
    struct get
    {
        static_assert(Index < sizeof...(Ts), "types_list::get index out of bounds");

    private:
        template <std::size_t CurrentIndex, typename ...Us>
        struct helper
        {
            using type = void;
        };

        template <std::size_t CurrentIndex, typename U, typename ...Us>
        struct helper<CurrentIndex, U, Us...>
        {
            using type = std::conditional_t<CurrentIndex == Index, U, typename helper<CurrentIndex + 1, Us...>::type>;
        };

    public:
        using type = typename helper<0, Ts...>::type;
    };

    template <template <typename...> typename TL, typename ...Ts>
    struct list_impl
    {
        inline static constexpr std::size_t size = sizeof...(Ts);

        template <std::size_t Index>
        using get = typename detail::get<Index, Ts...>::type;
    };
}

template <typename ...Ts>
struct types_list : public detail::list_impl<types_list, Ts...>
{
};

template <typename T, typename ...Ts>
struct types_list<T, Ts...> : public detail::list_impl<types_list, T, Ts...>
{
private:
    using impl = detail::list_impl<types_list, T, Ts...>;

public:
    using front = typename impl:: template get<0>;
    using back = typename impl:: template get<impl::size - 1>;
};

using t = types_list<int, double>::front;
using t2 = types_list<int, double>::back;
using t3 = types_list<int, char, double>::get<1>;

int main()
{
    t x = 10;
    t2 y = 1.4;
    t3 z = 'a';
}
编辑:更详细的示例https://pastebin.com/snRC0EPi

最佳答案

看来确实是错误。要引用当前实例,通常可以省略当前类型的模板参数。这就是MSVC在这里所做的。因为模板需要模板模板参数,所以会导致错误。
但是,为什么要使用模板template参数呢?对于CRTP,请使用“绑定(bind)模板类型”。

更新
如果您需要使用新参数实例化模板,则可以使用帮助程序类型轻松完成此操作:

namespace helper{
    template<
        typename VariadicType
    >
    class GetTemplateOfVariadicType{
    };

    template<
        template <typename...> typename Template,
        typename... Ts
    >
    class GetTemplateOfVariadicType<Template<Ts...>>
    {
    public:
        template<typename... T>
        using type = Template<T...>;
    };
}
用法:
using OtherTL = typename ::helper::GetTemplateOfVariadicType<TL>::template type<int, bool, char>;
看到这里:godbolt

10-02 01:38
查看更多