lea*_*ika 13 c++ c++11 c++14 c++17
我尝试使用三个编译器(msvc2017,gcc8.2,clang7.0)的下一个代码,msvc2017一直工作,但gcc和clang没有.我想了解我的代码有什么问题,以及为什么编译器无法编译它.
#include <cassert>
#include <iostream>
#include <cstdlib>
class Downloader
{
public:
struct Hints
{
int32_t numOfMaxEasyHandles = 8;
//Hints(){} // <= if I uncomment this all works gcc+clang+msvc
//Hints() = default; // <= if I uncomment this neither clang no gcc works (msvc - works)
};
static Downloader *Create(const Hints &hints = Hints());
};
Downloader* Downloader::Create(const Hints &hints)
{
std::cout << hints.numOfMaxEasyHandles << std::endl;
return nullptr;
}
int main()
{
return 0;
}
Run Code Online (Sandbox Code Playgroud)
您可以在https://wandbox.org/上自行使用此代码,并查看错误:
prog.cc:16:58: error: default member initializer for 'Downloader::Hints::numOfMaxEasyHandles' required before the end of its enclosing class
static Downloader *Create(const Hints &hints = Hints());
^
prog.cc:11:37: note: defined here
int32_t numOfMaxEasyHandles = 8;
^~~~
Run Code Online (Sandbox Code Playgroud)
为什么gcc和clang即使没有注释也不能编译这段代码Hints() = default?我的编译命令:
$ g++ prog.cc -std=gnu++2a$ clang++ prog.cc -std=gnu++2a但如果我取消注释Hints(){}所有三个编译器的工作原理.也许是编译器错误?提前致谢.
tro*_*zen 10
截至 2021 年,它仍然没有修复,但作为一种解决方法,我正在使用这样的东西:
namespace detail {
struct DownloaderHints
{
int32_t numOfMaxEasyHandles = 8;
};
}
class Downloader {
public:
using Hints = details::DownloaderHints;
static Downloader *Create(const Hints &hints = Hints());
};
Run Code Online (Sandbox Code Playgroud)
这是我的解决方法:
class Downloader
{
public:
struct Hints
{
int32_t numOfMaxEasyHandles = 8;
};
static Hints default_hints() { return {}; }
static Downloader *Create(const Hints &hints = default_hints());
};
Run Code Online (Sandbox Code Playgroud)
或者:
...
struct Hints
{
int32_t numOfMaxEasyHandles = 8;
static Hints Default() { return {}; }
};
static Downloader *Create(const Hints &hints = Hints::Default());
...
Run Code Online (Sandbox Code Playgroud)
这是在 Godbolt 上。这样做的好处是可以保持Hints聚合,所以我们仍然可以写:
return Downloader::Create({
.numOfMaxEasyHandles = 24,
});
Run Code Online (Sandbox Code Playgroud)
截至 2022 年,该错误仍未修复,但另一种解决方法是在 .cpp 文件中默认构造函数:
class Downloader
{
public:
struct Hints
{
int32_t numOfMaxEasyHandles = 8;
Hints();
};
static Downloader *Create(const Hints &hints = Hints());
};
// In .cpp:
Downloader::Hints::Hints() = default;
Run Code Online (Sandbox Code Playgroud)
但请注意,这会阻止Hints聚合,例如可能会阻止使用专用初始化器。
这是一个clang和gcc错误,我们为此提供一个clang错误报告:在函数的默认参数的封装类的定义中需要'm'的默认成员初始化程序,具有以下示例:
#include <limits>
class A
{
public:
class B
{
public:
explicit B() = default;
~B() = default;
private:
double m = std::numeric_limits<double>::max();
};
void f(double d, const B &b = B{}) {}
};
int main()
{
A a{};
a.f(0.);
}
Run Code Online (Sandbox Code Playgroud)
会产生以下类似的诊断:
t.cpp(15,34): error: default member initializer for 'm' needed within definition of enclosing class 'A' outside of member functions
void f(double d, const B &b = B{}) {}
^
t.cpp(12,20): note: default member initializer declared here
double m = std::numeric_limits<double>::max();
^
Run Code Online (Sandbox Code Playgroud)
理查德·史密斯(Richard Smith)指出这是一个错误:
关于注释#0:如果我们要彻底解决此问题,则应使用与延迟模板解析相同的技术:教Sema调用解析器以按需解析延迟区域。然后,我们仅拒绝存在实际依赖周期的情况。
虽然没有详细解释原因。
| 归档时间: |
|
| 查看次数: |
548 次 |
| 最近记录: |