我在显式和自动尾随返回类型之间发现了一个奇怪的区别.
在下面的代码中,我们定义了一个在整数和iter函数上模板化的结构,它将这种类型的一个对象作为参数.返回类型取决于在递减模板值后调用自身的结果.
为了打破实例化循环(或者我认为),我提供了一个返回非依赖类型的特化.
我们有一个玩具主体来实例化模板.
这是一些代码:
template<int i> struct Int {};
constexpr auto iter(Int<0>) -> Int<0>;
template<int i> constexpr auto iter(Int<i>) -> decltype(iter(Int<i-1>{}));
int main(){
decltype(iter(Int<10>{})) a;
}
Run Code Online (Sandbox Code Playgroud)
此代码在gcc 4.9和clang 3.5中都不起作用.两者都触发无限实例化(它们与专用基本情况不匹配).
rec.cpp:11:62: fatal error: recursive template instantiation exceeded maximum depth of 256
template<int i> constexpr auto iter(Int<i>) -> decltype(iter(Int<i-1>{}));
Run Code Online (Sandbox Code Playgroud)
现在,如果我们使用C++ 14 decltype(auto)并且我们为模板提供了一个返回完全相同的东西:
template<int i> struct Int {};
constexpr auto iter(Int<0>) -> Int<0>;
template<int i>
constexpr auto iter(Int<i>) -> decltype(auto) {
return iter(Int<i-1>{});
}
int main(){
decltype(iter(Int<10>{})) a;
}
Run Code Online (Sandbox Code Playgroud)
这现在适用于两个编译器并按预期运行.
我尝试了不同的方式来表达专业化并稍微移动一下(要小心它的位置),但这并没有阻止它的自焚;( …
我不明白为什么以下代码在使用构造函数样式的转换时无法编译:
template<typename T> void foo(const T& t){}
int main(){
foo(unsigned char(0));
}
Run Code Online (Sandbox Code Playgroud)
错误是:
error: expected primary-expression before ‘unsigned’ 对于gcc.error: expected '(' for function-style cast or type construction 为了铿锵但是这三种语法是正确的:
template<typename T> void foo(const T& t){}
int main(){
// c-style cast
foo((unsigned char)0);
// without unsigned
foo(char(0));
// aliased unsigned char
typedef unsigned char uchar;
foo(uchar(0));
}
Run Code Online (Sandbox Code Playgroud)
所以这种类型的空间显然应该归咎于此.
我认为它可能与我们的老朋友有点相关的最令人烦恼的解析,所以我尝试了统一初始化语法,这应该摆脱这种模糊,但没有运气:
template<typename T> void foo(const T& t){}
int main(){
foo(unsigned char{0});
}
Run Code Online (Sandbox Code Playgroud)
但仍然:
error: expected primary-expression before ‘unsigned’ …我猜答案是"不",但从编译器的角度来看,我不明白为什么.
我制作了一个非常简单的代码,它使得编译器诊断非常糟糕(clang和gcc),但是我想确认代码在报告错误诊断之前没有格式化.我应该指出,这些不是编译器错误,输出在所有情况下都是正确的,但我对这些警告有疑问.
请考虑以下代码:
#include <iostream>
int main(){
int b,a;
b = 3;
b == 3 ? a = 1 : b = 2;
b == 2 ? a = 2 : b = 1;
a = a;
std::cerr << a << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
赋值a是一个重言式,意思是a将在两个三元语句之后初始化,无论如何b.GCC对此代码非常满意.Clang更聪明,发现了一些愚蠢的东西warning: explicitly assigning a variable of type 'int' to itself [-Wself-assign],但没什么大不了的.
现在是相同的事情(至少在语义上),但语法更短:
#include <iostream>
int main(){
int b,a = (b=3,
b == 3 ? a = 1 …Run Code Online (Sandbox Code Playgroud) 我对链接器有一个恼人的问题.我想将一些符号从共享库链接到静态库,但不导出它的符号(即,我不能简单地合并库或链接--whole-archive).我想要的是链接(如在链接可执行文件,解决未定义的符号)我的共享库到静态库并删除未定义的符号.
我正在寻找的东西可能只是一个链接器选项,但我无法指责它.
我会尝试尽我所能地描述问题(这不是那么容易),然后提供玩具最小的例子来玩.
编辑:问题已经解决,解决方案发布在问题的底部
简要说明:
我想使用这个LD_PRELOAD技巧来捕获可执行文件中的一些函数调用.此可执行文件链接到第三方共享库,该库包含我要捕获的函数的函数定义.
这个第三方库还包含来自另一个库的符号,我也在我的库中使用它,但是使用不同的(不兼容的)版本.
我想要做的是编译我的共享库,并在编译时将其与最后(静态)库的定义链接,而不导出符号,以便我的共享库使用与我想要捕获的版本不同的版本.
简化问题描述
我有一个第三方库libext.so,我没有源代码.这定义了一个函数bar并使用了foo另一个库中的函数,但符号都在那里定义:
$> nm libext.so
0000000000000a16 T bar
00000000000009e8 T foo
Run Code Online (Sandbox Code Playgroud)
正如我所提到的,foo是一个外部依赖,我想使用更新的版本.我有一个更新的库,让我们称之为libfoo.a:
$> nm libfoo.a
0000000000000000 T foo
Run Code Online (Sandbox Code Playgroud)
现在的问题是,我想创造出重新定义了一个动态库bar,但我想我的图书馆使用的定义foo从libfoo.a,我想从函数libext.so调用的函数foo从libext.so.换句话说,我想要我的库的编译时链接libfoo.a.
我正在寻找的是定义一个使用libfoo.a但不导出其符号的库.如果我链接我的库libfoo.a,我得到:
$> nm libmine.so
0000000000000a78 T bar
0000000000000b2c T foo
Run Code Online (Sandbox Code Playgroud)
这意味着我既超载foo和bar(我不希望重写foo).如果我没有链接我的图书馆libfoo.a,我得到:
$> nm …Run Code Online (Sandbox Code Playgroud) 简短问题:运营商是否具有针对内部链接的重载解析的特殊模板查找规则,或者底层的代码是GCC中运营商的模板重载解决错误?
细节:我会带你完成我的推理,而不是粘贴一大堆代码.让我们从一些简单的代码开始:
#include <iostream>
template<typename T> struct A{ T b; };
struct B{};
template<typename T>
void foo (const A<T>&a) { foo(a.b); }
void foo (const B&) { std::cout << "hello"; }
int main(){
A<B> b;
foo(b);
}
Run Code Online (Sandbox Code Playgroud)
以上打印"hello",一切都很好.
现在让我们将它们foo放在匿名命名空间中:
namespace {
template<typename T>
void foo (const A<T>&a) { foo(a.b); }
void foo (const B&) { std::cout << "hello"; }
}
Run Code Online (Sandbox Code Playgroud)
代码现在无法编译.Clang说error: call to function 'foo' that is neither visible in the template definition …
有没有人知道如何简化Nautilus中的标准上下文(右键单击)菜单?我正在为不经常使用计算机的人制作一个非常简化的界面,我想使用Nautilus作为文件管理器.我已经使用nautilus-action在上下文菜单中添加了一些操作,但我想删除标准的复制/粘贴/创建文件夹/创建链接以及几乎所有其他操作.我没有在我的系统上找到任何XML或其他配置文件,我在Nautilus的资源上使用grep来查找它的位置,因为我怀疑它是硬编码的,但到目前为止还没有任何乐趣.
我无法理解为什么当有一个完美的转发构造函数时,绑定到const参考参数的临时工的生命周期被缩短.首先,我们知道有关临界参数的临时参数:它们持续完整表达式:
在函数调用(5.2.2)中与引用参数的临时绑定将持续存在,直到包含该调用的完整表达式完成为止
但是我发现这种情况并非如此(或者我可能只是误解了完整表达式是什么).让我们举一个简单的例子,首先我们用详细的构造函数和析构函数定义一个对象:
struct A {
A(int &&) { cout << "create A" << endl; }
A(A&&) { cout << "move A" << endl; }
~A(){ cout << "kill A" << endl; }
};
Run Code Online (Sandbox Code Playgroud)
还有一个对象包装器B,它将用于参考折叠:
template <class T> struct B {
T value;
B() : value() { cout << "new B" << endl; }
B(const T &__a) : value(__a) { cout << "create B" << endl; }
B(const B &p) = default;
B(B && o) = default;
~B(){ cout << …Run Code Online (Sandbox Code Playgroud) 我认为扩展参数包具有以下行为:
// for Args ... p
f(p)...;
// was equivalent to
f(p1); f(p2); ...; f(pn);
Run Code Online (Sandbox Code Playgroud)
但我刚刚发现gcc(4.6,4.7和4.8)反过来说:
f(pn); ...; f(p2); f(p1);
Run Code Online (Sandbox Code Playgroud)
而clang按照我的预期做到了.
这是GCC中的错误还是根据标准有效?
最小的例子
#include <iostream>
#include <string>
template<typename T>
bool print(const unsigned index, const T& value){
std::cerr << "Parameter " << index << " is " << value << std::endl;
return true;
}
template<typename ... Args>
void printAll(Args ... args){
unsigned i = 0;
[](...){}(print(i++, args)...);
}
int main(){
int a = 1; float b = 3.14; std::string …Run Code Online (Sandbox Code Playgroud)