背景:
C++ 17具有两个重要功能:聚合初始化模板类型推导(用于类)。聚合初始化允许您实例化字段,而无需复制或移动它们,而模板类型推导使您可以实例化字段,从而不必指定参数的类型。
以下代码中的Wrapper类就是一个示例。只要HAVE_MOVE_AND_COPY保持未定义状态,它就具有聚合初始化,但是模板类型推导不起作用。
另一方面,如果定义了HAVE_MOVE_AND_COPY,则可以进行模板类型推导,但是聚合初始化会中断。我怎么都可以?

#include <cstdio>
#include <utility>

template<class T>
struct Wrapper {
    T value;
   #ifdef HAVE_MOVE_AND_COPY
    Wrapper(T const & val) : value{val} {}
    Wrapper(T && val) : value{std::move(val)} {}
   #endif
    Wrapper(Wrapper const &) = default;
    Wrapper(Wrapper &&) = default;


};

struct VocalClass {
    VocalClass() { puts("VocalClass()"); }
    VocalClass(VocalClass const&) { puts("VocalClass(VocalClass const &)"); }
    VocalClass(VocalClass &&) { puts("VocalClass(VocalClass &&)"); }
};

int main() {
    Wrapper<VocalClass> w { VocalClass() };

   #ifdef TRY_DEDUCTION
    Wrapper w2 { VocalClass() };
   #endif
}
例:
没有移动或复制发生,但是您没有模板推导:
$ c++ -std=c++17 example.cc && ./a.out
VocalClass()
有模板推论,但是VocalClass被移动了:
$ c++ -DHAVE_MOVE_AND_COPY -DTRY_DEDUCTION -std=c++17 example.cc && ./a.out
VocalClass()
VocalClass(VocalClass &&)
VocalClass()
VocalClass(VocalClass &&)
没有HAVE_MOVE_AND_COPY,模板类型推导将中断:
sky@sunrise:~$ c++ -DTRY_DEDUCTION -std=c++17 example.cc && ./a.out
example.cc: In function ‘int main()’:
example.cc:27:31: error: class template argument deduction failed:
     Wrapper w2 { VocalClass() };
                               ^
example.cc:27:31: error: no matching function for call to ‘Wrapper(VocalClass)’
example.cc:12:5: note: candidate: ‘template<class T> Wrapper(Wrapper<T>&&)-> Wrapper<T>’
     Wrapper(Wrapper &&) = default;
     ^~~~~~~
example.cc:12:5: note:   template argument deduction/substitution failed:
example.cc:27:31: note:   ‘VocalClass’ is not derived from ‘Wrapper<T>’
     Wrapper w2 { VocalClass() };
                               ^
example.cc:11:5: note: candidate: ‘template<class T> Wrapper(const Wrapper<T>&)-> Wrapper<T>’
     Wrapper(Wrapper const &) = default;
     ^~~~~~~
example.cc:11:5: note:   template argument deduction/substitution failed:
example.cc:27:31: note:   ‘VocalClass’ is not derived from ‘const Wrapper<T>’
     Wrapper w2 { VocalClass() };
                               ^
example.cc:5:8: note: candidate: ‘template<class T> Wrapper(Wrapper<T>)-> Wrapper<T>’
 struct Wrapper {
        ^~~~~~~
example.cc:5:8: note:   template argument deduction/substitution failed:
example.cc:27:31: note:   ‘VocalClass’ is not derived from ‘Wrapper<T>’
     Wrapper w2 { VocalClass() };


有什么办法可以同时进行模板类型推导和聚合初始化?

最佳答案

首先,该术语是“类模板参数推导”。

其次,您需要的是推导指南:

template<class T>
struct Wrapper {
    T value;
};

template <typename T>
Wrapper(T) -> Wrapper<T>; // this is a deduction guide

如果没有构造函数,则需要其他方法来指导推导。这就是它的用途,它允许:
Wrapper w{4}; // ok, Wrapper<int>

关于c++ - 同时进行汇总初始化和模板推导,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/53137035/

10-11 16:28