状态的gcc文档__attribute__((pure))
:
除返回值外,许多函数都没有效果,它们的返回值仅取决于参数和/或全局变量.这样的函数可以像算术运算符那样经受公共子表达式消除和循环优化.应使用属性声明这些函数
pure
.
仅依赖于参数意味着什么?考虑:
struct Wrapper {
int i;
int get() const { return i; }
void set(int x) { i = x; }
};
Run Code Online (Sandbox Code Playgroud)
标记Wrapper::get()
为pure
成员函数是否有效?它只取决于隐式Wrapper
实例,但数据可能会改变.
我在推导一个c ++数组的单个元素的类型时遇到了问题.
我想做到这样的事情:
template <class T>
struct array_element { };
template <class T>
struct array_element<T[]> {
using type = T;
};
int main() {
int a[5] = {1, 2, 3, 4, 5};
array_element<decltype(a)>::type element = a[0];
}
Run Code Online (Sandbox Code Playgroud)
但是代码显然不能编译(int [5]与T []不匹配)...
考虑一个简单的例子:
template <class T>
struct foo {
template <template <class> class TT>
foo(TT<T>&&) {}
foo(foo<T>&&){}
foo() {}
};
int main() {
foo f1(foo<int>{}); //case 1.
foo<int> f2(foo<int>{}); //case 2.
}
Run Code Online (Sandbox Code Playgroud)
情况1.在clang中的foo类的模板参数推导中导致模糊,但在gcc中没有.我认为模板函数(这里 - 构造函数)在重载决策中具有较低的优先级.这不是这种情况吗?
错误信息:
prog.cc:10:14: error: ambiguous deduction for template arguments of 'foo'
foo f1(foo<int>{}); //case 1.
^
prog.cc:4:5: note: candidate function [with T = int, TT = foo]
foo(TT<T>&&) {}
^
prog.cc:5:5: note: candidate function [with T = int]
foo(foo<T>&&){}
^
1 error generated.
Run Code Online (Sandbox Code Playgroud)
c++ templates language-lawyer template-argument-deduction c++17
在c ++引用中,我没有看到std::stringstream
构造函数接受rvalue引用std::string
.是否有任何其他辅助函数将字符串移动到字符串流而没有开销,或者是否有一个特殊的原因来制定这样的限制?
考虑一下代码:
#include <iostream>
template <class... Ts>
struct outer {
template <class... ITs>
struct inner {
static constexpr bool value = false;
};
template <class... ITs>
struct inner<Ts..., ITs...> {
static constexpr bool value = true;
};
};
int main() {
std::cout << outer<int, float, double>::inner<int, float, double, int>::value << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
代码用clang ++编译但不用g ++编译产生错误:
temp3.cc:11:11:错误:参数包参数'Ts ...'必须位于模板参数列表的末尾
Run Code Online (Sandbox Code Playgroud)struct inner<Ts..., ITs...> { ^
正如我已经在这里建立的那样,内部阶级的部分专业化应该是合法的.
编辑: 为了完整性,值得补充一点,上面代码的clang警告他可能在推导IT参数时遇到问题,但没有任何问题......
c++ templates template-specialization variadic-templates c++11
从C++ 11开始,就可以创建用户定义的文字.正如预期的那样,可以从这些文字返回复杂的结构.但是,在尝试使用此类运算符时123_foo.bar()
:
struct foo {
int n;
int bar() const { return n; }
};
constexpr foo operator ""_foo(unsigned long long test)
{
return foo{ static_cast<int>(test) };
}
int main() {
return 123_foo.bar();
}
Run Code Online (Sandbox Code Playgroud)
海湾合作委员会和克朗拒绝了,说他们找不到operator""_foo.bar
.MSVC接受它.如果我改为写123_foo .bar()
,那么所有三个编译器都接受它
谁在这?是123_foo.bar()
以往任何时候都有效吗?
一些额外的信息:
std::chrono
文字也存在问题我倾向于认为这是一个GCC和Clang错误,因为.
它不是有效标识符的一部分.
考虑一个例子:
template <void (*Foo)()>
struct S {
};
int main() {
struct A {
static void x() { }
};
S<&A::x> s;
}
Run Code Online (Sandbox Code Playgroud)
代码在clang中编译,gcc认为x
没有链接...对于非常类似的例子,只是在使用lambda表达式时:
template <void (*Foo)()>
struct S {
};
int main() {
auto lambda = []{};
S<+lambda> s;
}
Run Code Online (Sandbox Code Playgroud)
gcc和clang都同意不编译代码:根据gcc,由unary +返回的函数没有链接,相反,clang状态表示对该函数的强制转换操作符未声明为constexpr.是否有任何理由不允许lambda强制转换为在constexpr上下文中使用的函数指针?
查找编译器和现场演示产生的以下错误:
gcc:
prog.cc:7:14:错误:'main():::: _ FUN'不是类型'void(*)()'的有效模板参数,因为'static constexpr void main():::: _ FUN( )'没有联系
prog.cc:7:8:注意:非constexpr函数'operator void(*)()'不能用于常量表达式
请考虑以下代码:
template <typename F, typename X0, typename X1, typename... Xs>
auto fold_left(F&& f, X0&& x0, X1&& x1, Xs&&... xs)
{
auto acc = f(x0, x1);
return ([&](auto y){ return acc = f(acc, y); }(xs), ...);
}
const std::string a{"a"}, b{"b"}, c{"c"}, d{"d"}, e{"e"};
const auto cat = [](auto x, auto y) { return "(" + x + ", " + y + ")"; };
Run Code Online (Sandbox Code Playgroud)
在调用和打印时fold_left(cat, a, b, c)
,g ++ 7和clang ++ 5输出:
((a,b),c)
当调用和打印fold_left(cat, a, b, c, …
根据这个答案,显然没有充分的理由说明为什么不允许结构化绑定是constexpr,但标准仍然禁止它.但是,在这种情况下,是否应该禁止在constexpr函数中使用结构化绑定?考虑一个简单的片段:
#include <utility>
constexpr int foo(std::pair<int, int> p) {
auto [a, b] = p;
return a;
}
int main() {
constexpr int a = foo({1, 2});
static_assert(a == 1);
}
Run Code Online (Sandbox Code Playgroud)
昨天我问了一个关于模板模板参数的扣除指南使用保证的问题.当Barry改变了对代码标准符合性确认的答案时,我感到非常惊讶.令我惊讶的是,实际上并不是因为扣除指南可以应用于模板模板参数,而是来自符合此合规性的标准部分,即[temp.param]/3:
标识符不遵循省略号的类型参数将其标识符定义为模板声明范围内的typedef-name(如果未声明
template
)或template-name(如果声明template
).
加上[temp.deduct.guide]/1和simple-template-id规则可以创建一个接受任何模板的通用推理指南.
#include <string>
template <class T>
struct Foo {
Foo(T) { }
};
template <template <class> class TT>
TT(const char *) -> TT<std::string>;
int main() {
Foo foo("abc");
}
Run Code Online (Sandbox Code Playgroud)
代码导致gcc因内部错误而崩溃,并导致clang中的编译错误.说实话,我并不是说代码应该在C++中实际允许,但认为当前的措辞确实使它符合要求.我错过了一些不允许代码的重要规则吗?
c++ template-templates language-lawyer template-argument-deduction c++17