类模板参数推导不适用于别名模板 [英] Class template argument deduction not working with alias template

查看:92
本文介绍了类模板参数推导不适用于别名模板的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请考虑下面粘贴的代码。我定义了一个非常简单的类,编译器会为该类生成一个隐式推导指南,以便可以在没有显式模板参数的情况下进行构造。但是,模板参数推导不能从简单的别名模板构造对象,该模板仅直接转发到目标类:

consider the code pasted below. I have defined a very simple class, for which the compiler generates an implicit deduction guide so it can be constructed without explicit template arguments. However, the template argument deduction does not work for constructing an object from a simple alias template which only forwards directly to the target class:

template< typename A, typename B >
struct Foo {
    Foo( A const &a, B const &b )
            : a_(a), b_(b)
    { }

    A a_;
    B b_;
};

template< typename A, typename B >
using Bar = Foo<A, B>;

auto foobar() {
    Foo r{1, 2};
    Bar s{3, 4};
    // ../src/geo/vector_test_unit.cpp: In function 'auto foobar()':
    // ../src/geo/vector_test_unit.cpp:16:6: error: missing template arguments before 's'
    //   Bar s{3, 4};
    //       ^
    return 1;
}

从上面的代码注释中可以看到,g ++给我一个错误关于使用没有模板参数的别名模板。我希望在这种情况下可以转发模板自变量推论。

As you can see from a code comment above, g++ is giving me an error about using the aliased template without template arguments. I was hoping in such an instance that template argument deduction would be forwarded.

所以,我的问题:这是通过当前设计的类模板自变量推导的提案措辞?还是这是一项未完成的功能或该功能的当前g ++实现中的错误?对于提案的作者或C ++ ISO委员会,这将是一个更大的问题,但是如果他们中的任何一个看到此问题:是否希望该功能的最终措辞包括启用诸如此类的别名模板,我可以理解,由于别名模板可以具有任何类型的模板参数,因此编译器不一定总能成功推断出目标,因此可以理解它们的含义吗?

So, my question: Is this by express design of the current wording of the proposal for class template argument deduction? Or is this an unfinished feature or bug in the current g++ implementation of the feature? And this would be more of a question for the authors of the proposal, or for the C++ ISO Committee, but if any of them see this: Would it be desired that the final wording of the feature include enabling alias templates such as this to also have implicit guides generated for them?

类模板参数,但在这种情况下,我希望编译器能够以与直接用于目标类相同的方式使用。

I can understand that since alias templates can have any kind of template parameters it may not always be possible for the compiler to successfully deduce the target class template arguments, but in a case like this I would expect that the compiler would be able to in the same way that it can directly for the target class.

我是使用几天前使用-std = c ++ 1z 从头构建的gcc进行构建。完整的版本信息是: gcc版本7.0.0 20161201(实验性)(自制的gcc HEAD- --with-jit)

I am building with gcc built from head only a few days ago, using --std=c++1z. The complete version info is: gcc version 7.0.0 20161201 (experimental) (Homebrew gcc HEAD- --with-jit)

推荐答案

这是我们在制定提案时考虑的功能,但由于我们设计不够好,最终还是从C ++ 17功能集中删除了该功能为了它。特别是,关于如何选择和将别名指南中的推理指南转换为别名模板的推理指南,存在一些细微之处。如果别名模板不是另一个模板的简单别名,该如何操作还存在一些悬而未决的问题。一些示例:

This was a feature that we considered when formulating the proposal, but it was eventually cut from the C++17 feature set because we didn't yet have a good enough design for it. In particular, there are some subtleties regarding how you select and transform deduction guides from the aliased template into deduction guides for the alias template. There are also open questions as to how to behave if the alias template is not a simple alias for another template. Some examples:

template<typename T> struct Q { Q(T); };     // #1
template<typename T> struct Q<T*> { Q(T); }; // #2
template<typename U> using QP = Q<U*>;
int *x;
Q p = x;  // deduces Q<int*> using #1, ill-formed
QP q = x; // deduces Q<int*> using #1, or
          // deduces Q<int**> using #2?

template<typename T> Q(T) -> Q<T>; // #3
QP r = x; // can we use deduction guide #3 here?

template<typename T> Q(T*) -> Q<T**>; // #4
int **y;
QP s = y; // can we use deduction guide #4 here?







template<typename T> struct A { typedef T type; struct Y {}; };
template<typename T> using X = typename A<T>::type;
template<typename T> using Y = typename A<T>::Y;
X x = 4;           // can this deduce T == int?
Y y = A<int>::Y(); // can this deduce T == int?

上述问题有不错的答案,但要解决这些问题会增加复杂性,似乎最好不要推导C ++ 17的别名模板,而不是匆忙处理有缺陷的东西。

There are decent answers to the above questions, but tackling them adds complexity, and it seemed preferable to disallow deduction for alias templates for C++17 rather than rush something flawed in.

更新[C ++ 20] :该主题已被重新讨论适用于C ++ 20,并且我们批准了 P1814R0 ,该类允许推导别名模板的类模板参数。

Update [C++20]: This topic was revisited for C++20, and we approved P1814R0, which permits class template argument deduction for alias templates.

原始示例现在有效。对于上面的示例:

The original example is now valid. For the examples above:


  • CTAD仍然仅考虑主模板中的构造函数。因此,在 QP q = x; 中,不考虑#2,而是使用#1的构造函数。该构造函数被隐式转换为 Q 的指南:

  • CTAD still only considers constructors from the primary template. So in QP q = x;, #2 is not considered, and instead #1's constructor is used. That constructor is implicitly converted into a guide for Q:

template<typename T> Q(T) -> Q<T>;

然后将其转换为别名模板 QP ,方法是从指南中推导 Q Q )的右侧别名模板( Q< U *> )的右手边,它得出 T = U * ,然后将其代入指南,从而产生以下内容:

which is then converted into a guide for the alias template QP by deducing the right-hand side of the guide for Q (Q<T>) from the right-hand side of the alias template (Q<U*>), which deduces T = U*, then substituting that back into the guide, thereby producing the equivalent of:

template<typename U> Q(U*) -> Q<U*>;
// ... which is effectively ...
template<typename U> QP(U*) -> QP<U>;
// ... except that explicit deduction guides are not
// permitted for alias templates

然后使用该指南来推导 q 的类型,从而推导 U = int ,因此 q 的类型为 Q< int *> ,因此 q 的初始化格式不正确。

That guide is then used to deduce the type of q, which deduces U = int, so the type of q is Q<int*>, so the initialization of q is ill-formed.

r 确实考虑了推导指南#3,如上所述,该指南已转化为 QP 的指南

The initialization of r does consider deduction guide #3, which is transformed into a guide for QP as described above

s 的初始化确实考虑了推导4。从 Q< U *> 推导 Q 不会产生任何推论,因此我们保留推论指南

The initialization of s does consider deduction guide #4; deducing Q<T**> from Q<U*> deduces nothing, so we retain the deduction guide

template<typename T> Q(T*) -> Q<T**>;

原样,但添加一个约束条件,即推导的结果必须与<$ c的形式匹配$ c> QP 。然后,我们推导 T = int ,将其代入以计算 Q < int **> ,并检查我们是否可以从 Q< int **>推断出 QP< U> ,我们可以。因此,将 s 的类型推导为 Q< int **>

as-is, but add a constraint that the result of deduction must match the form of QP. We then deduce T = int, substitute that in to compute a result type of Q<int**>, and check that we can deduce QP<U> from Q<int**>, which we can. So the type of s is deduced as Q<int**>.

CTAD >也许是:: stuff :: templatename< args> )。因此, X Y 都是不可推论的。

CTAD for alias templates is only supported where the right-hand side of the alias template is a simple-template-id (of the form maybe::stuff::templatename<args>). So neither X nor Y is deducible.

这篇关于类模板参数推导不适用于别名模板的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆