gpt4 book ai didi

c++ - 同时具有聚合初始化和模板推导

转载 作者:行者123 更新时间:2023-11-30 03:20:04 26 4
gpt4 key购买 nike

背景:

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/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com