当我们想在 astatic_assert中使用 a 时,if constexpr我们必须使条件依赖于某个模板参数。有趣的是,当代码包含在 lambda 中时,gcc 和 clang 不同意。
以下代码使用 gcc 进行编译,但 clang 会触发断言,即使if constexpr不能为真。
#include <utility>
template<typename T> constexpr std::false_type False;
template<typename T>
void foo() {
auto f = [](auto x) {
constexpr int val = decltype(x)::value;
if constexpr(val < 0) {
static_assert(False<T>, "AAA");
}
};
f(std::integral_constant<int, 1>{});
}
int main() {
foo<int>();
}
Run Code Online (Sandbox Code Playgroud)
它可以很容易地通过用固定False<T>通过False<decltype(x)>。
所以问题是:哪个编译器是正确的?我认为 gcc 是正确的,因为 中的条件static_assert取决于T,但我不确定。
只要内存不泄漏,C++20 就允许在 constexpr 函数中分配堆。然而 GCC 和 Clang 在比较两个动态分配对象的地址是否是一个常量表达式的问题上存在分歧。
以下代码段可以用 Clang 编译,但不能用 gcc 编译。
constexpr bool foo() {
int* a = new int(4);
int* b = new int(4);
bool result = a == b;
delete a;
delete b;
return result;
}
constexpr bool x = foo(); // GCC: error: '(((int*)(& heap deleted)) == ((int*)(& heap deleted)))' is not a constant expression
Run Code Online (Sandbox Code Playgroud)
以下在两个编译器上都可以正常工作
constexpr bool foo2() {
int a = 4;
int b = 5;
bool result = &a == &b;
return …Run Code Online (Sandbox Code Playgroud) 以下示例使用 gcc 编译,但不使用 clang 编译。哪个编译器是正确的,为什么?
#include <utility>
struct Foo {
private:
template<typename T>
static int f();
public:
template<typename U>
using T = decltype(f<U>());
};
int main () {
static_assert(std::is_same_v<Foo::T<float>, int>);
}
Run Code Online (Sandbox Code Playgroud)
Clang 抱怨说'f' is a private member of 'Foo'。我认为这是不正确的,因为f是从内部访问的Foo,因此应该是可见的。有趣的是,如果T不是模板,它也能工作。
现场代码在这里。
我想知道这两个字符串 UDL 之间的区别。虽然第一个编译得很好,但第二个出现错误。
唯一不同的是,Literal1使用std::array作为存储,同时Literal2使用const char *。
我可以轻松地Literal2显式构造一个,但是一旦我尝试使用 UDL 编译就会失败,并且'"123"' is not a valid template argument of type 'const char*' because '"123"' is not a variable. 有趣的是,如果我不在p构造函数中初始化,它也可以很好地编译。
template < size_t size >
struct Literal1 : std::array<char,size>
{
constexpr Literal1(char const (&str)[size+1]) { for (size_t ii = 0; ii < size; ++ii) (*this)[ii] = str[ii]; }
};
template < size_t size > Literal1(char const (&str)[size]) -> Literal1<size-1>;
template …Run Code Online (Sandbox Code Playgroud) 我试图在 CRTP 类中创建一个“转换复制构造函数”,如下所示: template struct Base;
template<typename Derived>
struct Base;
template<template<typename, typename...> class DerivedType, typename T, typename... Rest >
struct Base<DerivedType<T, Rest...>> {
Base() = default;
template<typename T2, typename... Rest2>
Base(const Base<DerivedType<T2, Rest2...>>& other) {
}
};
template<typename T>
struct Child : Base<Child<T>> {
using MyBase = Base<Child<T>>;
Child() = default;
template<typename T2>
Child(const Child<T2>& other) : MyBase(other) {}
};
int main() {
Child<int> cti;
Child<float> ctf = cti;
}
Run Code Online (Sandbox Code Playgroud)
该代码可以使用 never gcc 版本进行编译,但不能使用其他编译器进行编译。他们拒绝它,因为模板参数太多:
<source>:11:21: error: too many template arguments …Run Code Online (Sandbox Code Playgroud) 我想知道为什么这个代码不能用 clang 15 编译,即使范围库在编译器支持页面上的 clang 15 中被标记为完全支持?它确实使用 g++12 进行编译,即使支持仅标记为部分,并且它使用 clang trunk 进行编译。
#include <ranges>
#include <vector>
int main() {
std::vector x{1,2,3,4};
auto y = x | std::views::filter([](auto i){ return i <2;});
}
Run Code Online (Sandbox Code Playgroud)
代码是否错误?如果是的话,有没有办法解决这个错误,直到 clang 16 发布为止。我猜范围-v3 会起作用,但也许有人知道如何仅使用标准库来修复它。
有趣的是,我在使用-stdlib=libstdc++and时遇到了不同的错误-stdlib=libc++:
error: invalid operands to binary expression ('std::vector<int>' and '_Partial<std::ranges::views::_Filter, decay_t<(lambda at <source>:7:37)>>' (aka '_Partial<std::ranges::views::_Filter, (lambda at <source>:7:37)>'))error: no member named 'views' in namespace 'std'