这段代码不能在 Clang (6,7,8,9,trunk) 中编译,但在 GCC (7.1, 8.1, 9.1) 中编译得很好:
template<class T> struct TypeHolder { using type = T; };
template<int i>
class Outer {
private:
template<class T>
static constexpr auto compute_type() {
if constexpr (i == 42) {
return TypeHolder<bool>{};
} else {
return TypeHolder<T>{};
}
}
public:
template<class T>
using TheType = typename decltype(Outer<i>::compute_type<T>())::type;
};
int main() {
Outer<42>::TheType<int> i;
}
Run Code Online (Sandbox Code Playgroud)
叮当告诉我:
<source>:17:49: error: 'compute_type' is a private member of 'Outer<42>'
Run Code Online (Sandbox Code Playgroud)
......这当然是,但我尝试访问该成员中同一类。我不明白为什么它不应该在那里访问。我是否遇到了(我应该提交)Clang 错误?
您可以在Godbolt 的编译器资源管理器中 …
I'm trying to get this is-class-defined-check to work, which relies on the fact that decltype(std::declval<Foo>().~Foo()) is void if Foo has a destructor (which it has if it is defined…) and is ill-formed otherwise, invoking SFINAE in this case.
However, I can't get the code to work with GCC 9.1, and that is because GCC 9.1 seems to consider that type to be void & if the destructor is defaulted, consider this example:
#include <type_traits>
class Foo {
public:
// …Run Code Online (Sandbox Code Playgroud) 我目前正在尝试在 C++20 下构建遗留代码库,我遇到了这样的事情:
\nsize_t someCount; // value comes from somewhere else\n\xe2\x80\xa6\nstd::vector<const char *[2]> keyValues(someCount);\nRun Code Online (Sandbox Code Playgroud)\n我不能轻易地将其更改为类似的内容,std::vector<std:array<const char *, 2>>因为它稍后会传递给我无法控制的某个 API。只要我不启用 C++20,上述令人厌恶的内容就可以在 Clang 和 GCC 甚至 MSVC 中正常编译,但它会在 C++20 中的 MSVC 中中断,正如您在Godbolt 中看到的那样。
我认为这与是否使用上述构造函数的DefaultInsertable要求有关(这实际上是标准强制执行的T唯一要求)。根据 cppreference(请参阅前面的链接),C++17 之前的 STL 实现使用放置 new 来默认构造元素,从 C++20 开始,用于类型。这可能会触发 MSVC 从 C++17 回归到 C++20。std::construct_atDefaultInsertable
该标准规定,DefaultInsertable如果该表达式格式良好,则为类型:
allocator_traits<A>::construct(m, p)\nRun Code Online (Sandbox Code Playgroud)\n所以就我而言,那就是:
\nconst char * dummy[2];\nusing Allocator = std::allocator<const char *[2]>;\nAllocator a;\n// …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用std::enable_if和SFINAE完全基于类的模板参数来切换类模板的方法的实现.例:
#include <type_traits>
template<class T1, class T2>
class Foo {
template<class InnerT, class ... Args>
typename std::enable_if<std::is_same<T1, T2>::value, void>::type
bar(InnerT param) {};
template<class InnerT, class ... Args>
typename std::enable_if<!std::is_same<T1, T2>::value, void>::type
bar(InnerT param) {};
};
int main() {
Foo<int, int> f;
}
Run Code Online (Sandbox Code Playgroud)
在这里,bar()应该表现不同根据是否T1与T2属于同一类型或不.但是,此代码无法编译.GCC和clang都没有告诉我任何有用的东西.我怀疑问题是std::enable_if条件不依赖于参数bar(),即不依赖于标准第17.8.2点第8点规定的直接上下文.
这个代码很好地支持了这个假设:
#include <type_traits>
class DummyClass {};
template<class T1, class T2>
class Foo {
template<class InnerT, class ... Args>
typename std::enable_if<std::is_same<T1, T2>::value ||
std::is_same<InnerT, …Run Code Online (Sandbox Code Playgroud) 我最近遇到过尝试将函数(而不是函数指针)放入 中的代码std::pair,该代码被 GCC 接受,但不被 Clang 接受。这导致我根据 C++ (17) 标准调查什么是“正确的”。考虑一下:
void foo(int) {}\n\n// (1) Not allowed in GCC, Clang or MSVC\nstd::pair<decltype(foo), decltype(foo)> myFirstPair;\n\n// (2) Compiles in GCC, fails in Clang and MSVC\nauto myPair = std::pair{foo, foo};\n\n// (3) Compiles in GCC, Clang and MSVC\nauto myOtherPair = std::make_pair(foo, foo);\nRun Code Online (Sandbox Code Playgroud)\n(也在编译器资源管理器中)
\n显然,您不能将函数类型作为成员(这将是推导出函数类型之一T1或T2之一的结果),但函数指针很好。事实上,这似乎就是编译成功的情况下发生的情况:对于,Clang 和 GCC 都推导了的类型。对于,GCC 也推论为。std::pair<T1, T2>void ()(int)(3)std::pair<void (*)(int), void (*)(int)>myOtherPair(2)std::pair<void (*)(int), void (*)(int)>myPair
我需要一些代码来检查某个模板是否属于参数包。为了实现对普通班级的检查,我使用了路易斯·迪昂(Louis Dionne)或奥古斯汀·贝格(AgustínBergé)概述的基于多重继承的方法。
这个想法是,您将包中的每个类T包装到一个PackEntry类中,然后PackIndex从所有PackEntry类中继承。这样,如果您正在寻找一个类A,您要做的就是检查a是否PackIndex可以转换为正确的PackEntry。将所有内容放在一起,看起来像这样:
#include <cstddef>
#include <utility>
template <class T>
struct PackEntry
{
using type = T;
};
template <class... Ts>
struct PackIndex : PackEntry<Ts>...
{};
template <class T, class... Ts>
struct PackSearcher
{
static constexpr std::false_type check(...);
// This overload is used if the PackIndex below
// derives from PackEntry<T>, the overload above
// otherwise.
static constexpr std::true_type …Run Code Online (Sandbox Code Playgroud) 我试图弄清楚GCC或Clang是否在这里以不同/错误的方式解释C++ 17标准.
这是我的代码,它使用GCC 8编译,但不使用Clang 6:
struct BoolHolder {
constexpr static bool b = true;
};
template<bool b>
class Foo {};
int main() {
BoolHolder b;
Foo<b.b> f; // Works
BoolHolder & br = b;
Foo<br.b> f2; // Doesn't work
}
Run Code Online (Sandbox Code Playgroud)
我不知道这是为什么.显然,b.b是一个有效的constexpr(或第一个Foo<b.b>无效).是br.b不是有效constexpr?为什么?对象或引用本身应该与它无关,因为我们在这里访问静态constexpr成员,对吧?
如果这真的无效C++ 17,那么GCC是否甚至不警告我(即使我启用了-Wall -Wextra -pedantic)这个事实应该被视为一个错误?
我试图找出以下代码在GCC 7中工作,但在GCC 8.1中没有.
代码的作用是:
MyGoodFriend(在全局命名空间中)Befriended在inner命名空间内定义一个类模板MyGoodFriend一个朋友的所有专业Befriended有问题的是
template<class FA>
friend class MyGoodFriend;
Run Code Online (Sandbox Code Playgroud)
我明白了问题所在.GCC 8.1要求我::MyGoodFriend在friend声明中使用完全限定的名称- 但是,GCC 7很满意MyGoodFriend.这是代码:
template<class A>
class MyGoodFriend;
namespace inner {
template<class T>
class Befriended {
private:
int i;
T t;
template<class FA>
friend class MyGoodFriend;
// This works for gcc 8.1:
// template<class FA>
//friend class ::MyGoodFriend;
};
} // namespace inner
template<class A>
class MyGoodFriend {
public:
void do_something() {
inner::Befriended<bool> …Run Code Online (Sandbox Code Playgroud) C++20 标准在 [vector.overview]/4 中声明:
如果分配器满足分配器完整性要求,则在实例化向量时可以使用不完整类型 T。T 应在引用所得向量专业化的任何成员之前完成。
默认分配器std::allocate确实满足allocator completeness requirements. 主要问题是“引用”在这种情况下意味着什么。我感到困惑的代码是以下代码的变体:
#include <vector>
class MyClass;
class MyContainer
{
std::vector<MyClass> member;
};
class MyClass {};
int main()
{}
Run Code Online (Sandbox Code Playgroud)
上面的代码可以在各种编译器中正常编译。如果我明确默认默认构造函数,它仍然可以编译:
#include <vector>
class MyClass;
class MyContainer
{
MyContainer() = default;
std::vector<MyClass> member;
};
class MyClass {};
int main()
{}
Run Code Online (Sandbox Code Playgroud)
然而,当我将默认构造函数定义为“空”时,会发生一些奇怪的事情。这是代码(位于编译器资源管理器):
#include <vector>
class MyClass;
class MyContainer
{
MyContainer() {};
std::vector<MyClass> member;
};
class MyClass {};
int main()
{}
Run Code Online (Sandbox Code Playgroud)
有了这个代码:
我正在尝试使用distplot()绘制分布,我想要
我认为(1)可以通过设置来实现norm_hist=False,但相对频率仍显示在y轴上:
但是没问题,我可以通过直接设置基础pyplot.hist图的'normed'关键字来解决此问题:
但是,现在我遇到的问题是,拟合函数(使用pyplot.plot创建)仍然可以在归一化值上使用,因此位于图的底部。我想完全摆脱拟合的情节。我怎么做?我以为设置fit=None可以解决问题,但是如您所见,事实并非如此。
任何帮助表示赞赏!
卢卡斯