嵌套模板类型的用户定义推导指南 Q1:命名空间范围内是否允许用户定义的推导指南?Q2 : 如果对 Q1 否,当 namespace-type 和嵌套类型模板参数 ?快速修复为什么?

问题描述

Q1:命名空间范围内是否允许用户定义的推导指南?

在这里的示例中,GCC 和 Clang 不会产生相同的行为:

#include <tuple>

template <typename T>
struct some_type;
template <template <typename...> typename T,typename ... Ts>
struct some_type<T<Ts...>>
{
    template <typename U>
    class nested
    {
        U member;
    public:
        nested(U &&){}
    };

    // non-namespace scope user-deduction-guide : OK with Clang,fix the deduction issue
    template <typename U>
    nested(U&&) -> nested<U>;
};

void func()
{
    using pack_type = std::tuple<int,char>;
    some_type<pack_type>::nested{
        [](auto &&){}
    };
}

简而言之,我们有一个模板参数类型,嵌套类型本身就是模板参数,模板参数之间没有任何关系。

template <typename T>
struct some_type;
template <template <typename...> typename T,typename ... Ts>
struct some_type<T<Ts...>>
{
    template <typename U>
    class nested // <- nested type,where `U` as no relationship with `T<Ts...>`
    {
        U member;
    public:
        nested(U &&);
    };
};

标准规定:http://eel.is/c++draft/temp.deduct.guide#3

[...] 演绎指南应在与相应类模板相同的范围内声明,并且对于成员类模板,应具有相同的访问权限。 [...]

Q2 : 如果对 Q1 ,当 namespace-type 和嵌套类型模板参数 ?

我希望语法接近:

template <template <typename...> typename T,typename ... Ts>
template <typename U>
some_type<T<Ts...>>::nested<U>::nested(U&&) -> nested<U>;

然而,nested<U>错误的,因为它需要一个推导类型......来推导它。

此外,这被解释为一个带有尾随返回类型 void 的函数。

template <template <typename...> typename T,typename ... Ts>
template <typename U>
typename some_type<T<Ts...>>::template nested<U>::nested(U&&) -> nested<U>;

感谢您的时间。

解决方法

快速修复

我发现的唯一解决方法是为 Clang 添加一个 user-defined deduction guide
这在可维护性方面次优

Live example on godbolt,
或查看下面的来源

为什么?

  • GCC 不允许在非命名空间上下文中使用推导指南,Clang 允许。
  • Clang 在这种情况下需要推导指南,GCC 不需要

注意:发布时,clang trunk 是 11.0.1,gcc trunk 是 10.2

#include <tuple>

template <typename T>
struct type
{
    template <typename U>
    struct nested
    {
        template <typename ... nested_Ts>
        nested(U &&,std::tuple<nested_Ts...> &&)
        {}

    };
    #if __clang__
    // here,user-defined deduction guide only for Clang
    template <typename U,typename ... Ts>
    nested(U&&,std::tuple<Ts...>&&) -> nested<U>;
    #endif
};

void instanciate_symbols()
{
    using type = type<int>;
    [[maybe_unused]] auto value = type::nested{'a',std::tuple{42,.42f}};
}

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...