这个最小的程序
template <typename X>
void foo (X x)
{
bar (x);
}
template <typename X>
void bar (X x)
{
}
int main ()
{
foo ([]{});
}
Run Code Online (Sandbox Code Playgroud)
用gcc编译(4.8.5和5.3)并且无法用clang编译(3.7)
我的分析如下.
bar
用于foo
和声明之后foo
,因此它在foo
定义点不可见.bar
在foo
实例化点可以找到唯一的方法是通过参数依赖查找.
双方的唯一参数foo
,并bar
在规定的拉姆达main
.
显然gcc认为它的类型是在全局命名空间中声明的,而clang则没有.因此,gcc可以bar
通过ADL和clang找不到.
当我们使用本地定义的类型时会发生同样的事情main
:
int main ()
{
struct K{};
foo (K()); // gcc compiles, clang complains
}
Run Code Online (Sandbox Code Playgroud)
看起来gcc在这里错了.根据标准的lambda类型是未命名的(expr.prim.lambda/3),因此它不应属于任何名称空间.据推测,本地类型也不应该属于全局命名空间.
分析是否正确?这是一个已知的gcc bug吗?
这个问题的灵感来自于这个问题.
试图编译数据memocombinators 0.4.3,得到以下错误:
Data/MemoCombinators.hs:119:10:
Could not deduce (Num a) arising from a use of `IntTrie.apply'
from the context (Ord a, Bits a)
Run Code Online (Sandbox Code Playgroud)
我认为Bits
以前是从中衍生出来的Num
.也许它很糟糕并且依赖性被删除了,但现在包装已经坏了.这有什么已知的解决方案吗?也许我正在使用一个坏版本的东西?
我暂时Num a
在我的软件包副本中添加了函数签名,但从长远来看这不是正确的.
我使用的是GHC 7.6.1,基数为4.6.0.0.
我在下面列出了我的代码。我收到很多错误,说 cout 和 endl 未在此范围内声明。我不知道我做错了什么或如何强制班级识别 cout?我希望我能正确解释我的问题。如果我注释掉方法(不是构造函数),它就可以工作。我可能只是在这里犯了一个新手错误 - 请帮忙。
using namespace std;
class SignatureDemo{
public:
SignatureDemo (int val):m_Val(val){}
void demo(int n){
cout<<++m_Val<<"\tdemo(int)"<<endl;
}
void demo(int n)const{
cout<<m_Val<<"\tdemo(int) const"<<endl;
}
void demo(short s){
cout<<++m_Val<<"\tdemo(short)"<<endl;
}
void demo(float f){
cout<<++m_Val<<"\tdemo(float)"<<endl;
}
void demo(float f) const{
cout<<m_Val<<"\tdemo(float) const"<<endl;
}
void demo(double d){
cout<<++m_Val<<"\tdemo(double)"<<endl;
}
private:
int m_Val;
};
int main()
{
SignatureDemo sd(5);
return 0;
}
Run Code Online (Sandbox Code Playgroud) 该程序由clang编译:
#include <mutex>
int main() {
std::mutex mtx;
const std::lock_guard<std::mutex>& lock(mtx);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
其他主要编译器拒绝它(我尝试过gcc,msvc和icc).这是来自gcc的错误消息:
error: invalid initialization of reference of type ‘const
std::lock_guard<std::mutex>&’ from expression of type ‘std::mutex’
Run Code Online (Sandbox Code Playgroud)
其他人给出了类似的错
是对还是错?这可以用一个不涉及库类的简单例子来复制吗?我试过但无济于事.
编辑这似乎是最小的再现:
struct A {};
struct X
{
explicit X(A&) {};
};
int main()
{
A a;
const X& x(a);
}
Run Code Online (Sandbox Code Playgroud)
有趣的是int
,替换A
确实触发了clang中的错误消息(这就是我最初无法重现的原因).
今天我发现了一个有趣的双libstdc ++ ABI案例,影响了库的兼容性.
长话短说,我有两个库都在内部使用std :: regex.一个是使用CXX11 ABI构建的,另一个不是.当这两个库在一个可执行文件中链接在一起时,它会在启动时崩溃(在main
输入之前).
库是不相关的,不公开提及任何std::
类型的接口.我认为这些库应该不受双重ABI问题的影响.显然不是!
这个问题可以通过这种方式轻松复制:
// file.cc
#include <regex>
static std::regex foo("(a|b)");
// main.cc
int main() {}
// build.sh
g++ -o new.o file.cc
g++ -o old.o file.cc -D_GLIBCXX_USE_CXX11_ABI=0
g++ -o main main.cc new.o old.o
./main
Run Code Online (Sandbox Code Playgroud)
输出是:
terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc
Aborted (core dumped)
Run Code Online (Sandbox Code Playgroud)
无论我做什么,问题仍然存在.file.cc
可以制作成两个独立的源文件,编译成单独的共享库,这两个std::regex
对象可能有不同的名称,它们可以是全局的,静态的或自动的(main
从那时起需要调用相应的函数).这些都没有帮助.
显然(这是我的简短调查的结果)libstdc ++正则表达式编译器有一些存储的内部静态数据,std::string
当两个ABI不兼容的代码片段试图使用该数据时,它会对std::string
对象的布局产生冲突的想法.
所以我的问题是:
这个问题在g ++/libstdc ++的几个版本中是可重现的(我尝试了一些从5.4到7.1).libc ++不会出现这种情况.
仍然在约束上玩存在主义(只是探索这个设计空间,我知道许多 Haskellers 认为它很糟糕)。有关更多信息,请参阅此问题。
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE ConstraintKinds #-}
{-# Language TypeApplications #-}
import GHC.Exts (Constraint)
class Foo a where
foo :: a -> Int
class Foo a => Bar a where
bar :: a -> String
instance Foo Int where
foo = id
instance Bar Int where
bar = show
data Obj cls = forall o. (cls o) => Obj o
fooable = Obj @Foo $ (42 :: Int)
barable = …
Run Code Online (Sandbox Code Playgroud) 写一个模块:
module Foo where
foo = 3.14
Run Code Online (Sandbox Code Playgroud)
编译它:
ghc -c Foo.hs
Run Code Online (Sandbox Code Playgroud)
加载它:
ghci -ignore-dot-ghci
GHCi, version 7.8.3: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude> :l Foo
[1 of 1] Compiling Foo ( Foo.hs, interpreted )
Ok, modules loaded: Foo.
Run Code Online (Sandbox Code Playgroud)
为什么GHCi不会选择编译代码?这是GHCi中的错误吗?
我试着跑-v
,不太有帮助.
更新
我发现,如果编译模块GHCi -fobject-code Foo
,GHCi将随后加载编译版本,即使没有-fobject-code
.
更新2
这一切都发生在Linux机器上的Ghc 7.8上.Windows机器上的Ghc 7.6不会出现此问题.
我试图将两个代码体集成到同一个进程中,每个进程以前都为各自的 GUI 工具包提供独立的事件循环——其中一个使用 Xt,另一个使用 Qt5。目的只是为了能够显示 Qt 子窗口,而不是像现在已经不复存在的 Qt/Motif 集成扩展那样实现完全集成。
我已经能够构建一个使用标准 Qt 事件循环运行的粗略原型,带有将 XCB 事件转换为 XEvents 的本机事件过滤器(使用 XESetWireToEvent + 其处理程序从 xEvents / X11 线格式转换)。然后它使用 XtDispatchEvent() 将这些 XEvent 直接分派到 Xt。此时,我可以运行该程序,并在同一个程序中创建 Xt/Motif 小部件和 Qt 小部件,使用菜单,绘制 2D 图形,并同时使用 Qt 和 Motif 小部件。
我遇到的问题是,在创建新的 Motif 对话框时会有很长的延迟。我已经将其追溯到 libXt 中的 _XtWaitForSomething(),最终归结为 X 服务器连接套接字上的 select() 或 poll()。对 _XtWaitForSomething() 的调用是 XtManageChild() 内部发生的窗口布局管理的结果。_XtWaitForSomething() 似乎正在检查事件队列中是否有待处理的事件。
我有几个问题:
当在同一个程序中同时使用 XCB 和 libX11 调用(使用 XCB 作为事件队列主控器)时,我是否可以期望来自经典 Xlib 的调用也能正常工作——例如通过 libX11 调用将事件发布到 XCB 事件队列,或者确定是否有通过旧的 libX11 调用在 XCB 事件队列中挂起的任何事件?
为什么 XtManageChild() 最终会阻塞 libXt 中的 _XtWaitForSomething()?看起来它可能正在等待几何更改事件。有趣的是,Qt 的平台层在单独的线程中读取 XCB …
以下是我的2014年标准草案N4140的一些摘录
22.5标准代码转换方面[locale.stdcvt]
3对于每三个码转换刻面
codecvt_utf8
,codecvt_utf16
和codecvt_utf8_utf16
:
(3.1) -Elem
是宽字符类型,如wchar_t
,char16_t
,或char32_t
.4对于方面
codecvt_utf8
:
(4.1) - 方面应在程序内转换UTF-8多字节序列和UCS2或UCS4(取决于大小Elem
).
这两段的一种解释是wchar_t
必须编码为UCS2或UCS4.我不喜欢它,因为如果它是真的,我们有一个深藏在图书馆描述中的语言的重要属性.我试图找到一个更直接的声明这个属性,但无济于事.
另一种解释是,wchar_t
编码不需要是UCS2或UCS4,在不实现的情况下,codecvt_utf8
也不适用wchar_t
.我不喜欢这种解释既得多,因为如果这是真的,也不char
也不是wchar_t
本地编码都是Unicode,似乎没有成为可移植的本地编码和Unicode之间进行转换的方式.
这两种解释中哪一种是正确的?还有另外一个我忽略了吗?
澄清我不是问关于wchar_t
软件开发适用性的一般意见,或者wchar_t
一个人的属性可以来自其他地方.我对标准的这两个特定段落感兴趣.我试图理解这些特定段落所包含或不包含的内容.
澄清2.如果4.1表示"facet将在UTF-8多字节序列和UCS2或UCS4之间进行转换,或者当前全局语言环境对wchar_t施加任何编码 ",则没有问题.它没有.它说的是什么.看起来如果使用std::codecvt_utf8<wchar_t>
,最终会得到一堆wchar_t
编码为UCS2或UCS4,而不管当前的全局语言环境.(无法指定区域设置或任何字符转换方面codecvt_utf8
).所以这个问题可以这样改写:转换结果是否可以直接用于当前的全局语言环境(和/或任何可能的语言环境),用于输出,wctype
查询等等?如果没有,它可用于什么?(如果上面的第二种解释是正确的,答案似乎是"没有").
我正在使用 boost::python 导出一些需要void*
. 他们在内部将其解释为原始内存(字节数组)。想read
和write
一些非常特殊用途的装置。
如何将 Python 传递bytearray
给这样的函数?
我试过使用,ctypes.c_void_p.from_buffer(mybytearray)
但这与函数的签名不匹配。
这是最小的例子:
#include <boost/python.hpp>
void fun_voidp(void*) {}
BOOST_PYTHON_MODULE(tryit) {
using namespace boost::python;
def("fun_voidp", fun_voidp);
}
Run Code Online (Sandbox Code Playgroud)
在蟒蛇方面:
import tryit
import ctypes
b = bytearray(100)
tryit.fun_voidp(b) # fail
tryit.fun_voidp(ctypes.c_void_p.from_buffer(b)) # fail
tryit.fun_voidp(ctypes.c_void_p.from_buffer(b).value) # fail
Run Code Online (Sandbox Code Playgroud)