感谢decltype作为返回类型,C++ 11使得引入装饰器非常容易.例如,考虑这个类:
struct base
{
void fun(unsigned) {}
};
Run Code Online (Sandbox Code Playgroud)
我想用其他功能来装饰它,因为我会用不同种类的装饰做几次,所以我首先介绍一个decorator简单地转发所有内容的课程base.在真实的代码中,这是通过以下方式完成的,std::shared_ptr这样我就可以删除装饰并恢复"裸"对象,并且所有内容都是模板化的.
#include <utility> // std::forward
struct decorator
{
base b;
template <typename... Args>
auto
fun(Args&&... args)
-> decltype(b.fun(std::forward<Args>(args)...))
{
return b.fun(std::forward<Args>(args)...);
}
};
Run Code Online (Sandbox Code Playgroud)
完美的转发,decltype真是太棒了.在实际代码中,我实际上使用的是一个只需要函数名称的宏,其余的都是样板文件.
然后,我可以引入一个derived为我的对象添加功能的类(derived不正确,同意,但它有助于理解这derived是一种base,虽然不是通过继承).
struct foo_t {};
struct derived : decorator
{
using decorator::fun; // I want "native" fun, and decorated fun.
void fun(const foo_t&) {}
};
int main()
{
derived d; …Run Code Online (Sandbox Code Playgroud) 我的项目包括一个大型C++库和Python绑定(通过Boost.Python).测试套件主要是在Python绑定之上编写的,我想用清理程序运行它,从ASAN开始.
我正在运行macOS(10.13.1 FWIW,但我也遇到了以前版本的问题),我似乎找不到在Python模块上运行ASAN的方法(我非常怀疑这与Boost.Python有关) ,我想它与其他技术一样).
这是一个简单的Python模块:
// hello_ext.cc
#include <boost/python.hpp>
char const* greet()
{
auto* res = new char[100];
std::strcpy(res, "Hello, world!");
delete [] res;
return res;
}
BOOST_PYTHON_MODULE(hello_ext)
{
using namespace boost::python;
def("greet", greet);
}
Run Code Online (Sandbox Code Playgroud)
这是我使用的Makefile,为MacPorts制作:
// Makefile
CXX = clang++-mp-4.0
CXXFLAGS = -g -std=c++14 -fsanitize=address -fno-omit-frame-pointer
CPPFLAGS = -isystem/opt/local/include $$($(PYTHON_CONFIG) --includes)
LDFLAGS = -L/opt/local/lib
PYTHON = python3.5
PYTHON_CONFIG = python3.5-config
LIBS = -lboost_python3-mt $$($(PYTHON_CONFIG) --ldflags)
all: hello_ext.so
hello_ext.so: hello_ext.cc
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) -shared -o $@ $< $(LIBS)
check: …Run Code Online (Sandbox Code Playgroud) 如何针对给定语法删除bison的shift-reduce冲突?
selection-stmt -> if ( expression ) statement |
if ( expression ) statement else statement
Run Code Online (Sandbox Code Playgroud)
提供修改后的语法的解决方案将受到高度赞赏.
这是我在Mac OS X上使用clang ++面临的问题的缩小版本.这是经过严格编辑以更好地反映真正的问题(第一次尝试描述问题并没有表现出问题).
我在C++中有一大块软件,在目标文件中有大量符号,所以我-fvisibility=hidden用来保持我的符号表小.众所周知,在这种情况下,必须特别注意vtable,我想我遇到了这个问题.然而,我不知道如何以一种令gcc和clang取悦的方式优雅地解决它.
考虑一个base具有向下转换运算符as的derived类,以及包含一些有效负载的类模板.pair base/ derived<T>用于实现类型擦除:
// foo.hh
#define API __attribute__((visibility("default")))
struct API base
{
virtual ~base() {}
template <typename T>
const T& as() const
{
return dynamic_cast<const T&>(*this);
}
};
template <typename T>
struct API derived: base
{};
struct payload {}; // *not* flagged as "default visibility".
API void bar(const base& b);
API void baz(const base& b);
Run Code Online (Sandbox Code Playgroud)
然后我有两个不同的编译单元提供类似的服务,我可以将其近似为相同功能的两倍:向下转换base为derive<payload>:
// bar.cc
#include "foo.hh" …Run Code Online (Sandbox Code Playgroud) 当我比较一个std::abs(int)和一个时,我正在收到有关签名与无签名比较的警告unsigned.事实上,std::abs返回签署的值.为什么选择这个?它将解决负值的问题,其绝对值不能用有符号的类型表示.
然后,是否有比这更清洁(即没有演员表)的东西以避免警告?
#include <cassert>
#include <cstdlib>
// max(1, lhs + rhs). (lhs must be > 0)
unsigned add(unsigned lhs, int rhs)
{
return
(0 < rhs || static_cast<unsigned>(-rhs) < lhs
? rhs + lhs
: 1);
}
int main()
{
assert(add(42, -41) == 1);
assert(add(42, 0) == 43);
assert(add(42, 1) == 43);
assert(add(42, -51) == 1);
}
Run Code Online (Sandbox Code Playgroud) 在下面的代码中,我正在尝试构建一个类型的网格.例如,在float和之间int,将结果推广到float:
float join(float f, int) { return f; }
float join(float f, float) { return f; }
Run Code Online (Sandbox Code Playgroud)
然后我介绍一种wrapper类型:
template <typename Inner>
struct wrapper
{
using inner_t = Inner;
inner_t value;
};
Run Code Online (Sandbox Code Playgroud)
其join操作行为很自然:
template <typename Inner1, typename Inner2>
auto
join(const wrapper<Inner1>& w1, const wrapper<Inner2>& w2)
-> wrapper<decltype(join(w1.value, w2.value))>
{
return {join(w1.value, w2.value)};
}
Run Code Online (Sandbox Code Playgroud)
它也可以join用"标量"类型编辑:
template <typename Inner1, typename T2>
auto
join(const wrapper<Inner1>& w1, const T2& value2)
-> wrapper<decltype(join(w1.value, value2))> …Run Code Online (Sandbox Code Playgroud) 在面向对象的语言中,使用简单的层次结构(Composite模式)实现AST(抽象语法树)并通过访问者遍历它们是相当普遍的.
在函数式编程语言中,使用变量/和类型,然后使用模式匹配,是正确的方法.
C++同时具有继承和Boost.Variants.我已经使用继承编写了几个AST层次结构,但我想从那些使用变体方法的人那里得到一些反馈.我想知道哪一个是"最好的",在性能(时间和空间)方面,而且在可维护性(易于创建树和遍历它们)方面.
我对实现hash-consing(保留每个公共子树的单个副本)的经验特别感兴趣,可能还有Boost.Flyweight.
谢谢!
当使用带有空右侧的规则编写("理论")语法时,总是使用诸如ε(或1)之类的符号来使这个空白显式:
A ? ? | a A
Run Code Online (Sandbox Code Playgroud)
Yacc和其他人的这种语法看起来就像
a: | 'a' a
Run Code Online (Sandbox Code Playgroud)
或"更糟"
a: { $$ = new_list(); }
| a 'a' { $$ = $1; $$->append($1); }
;
Run Code Online (Sandbox Code Playgroud)
事实上,在"真实世界语法"(Yacc,Bison等)规则的这个空的右侧部分没有明确标记为空的麻烦我:很容易错过rhs空的事实,或者更糟糕的是:忘记插入|并实际使用中规则操作:
a: { $$ = new_list(); }
a 'a' { $$ = $1; $$->append($1); }
;
Run Code Online (Sandbox Code Playgroud)
1)我不知道有任何工具可以提供显式空rhs的方法.有吗?
Bison的未来版本可能支持专用符号,在非空rhs中使用时会出现错误,而在留下隐式空rhs时会出现警告.
2)人们认为这有用吗?
3)你建议的符号是什么?
目前,候选人是$empty:
a: $empty { $$ = new_list(); }
| a 'a' { $$ = $1; $$->append($1); }
;
Run Code Online (Sandbox Code Playgroud)
选择的语法是%empty:
a: %empty { $$ = …Run Code Online (Sandbox Code Playgroud) 编辑:如果它的TLDR,只是跳到底部.我问的地方:如何配置autotools项目以使用静态库?
我正在使用几个开源库,我正在尝试在Clang的清洁剂下运行他们的测试套件.要在Clang清理程序下运行,我们需要(1)指定一些选项,以及(2)根据需要链接Clang的Compiler-RT中的静态库.注意:没有动态库或共享对象.
设置选项很简单:
export DYLD_FALLBACK_LIBRARY_PATH=/usr/local/lib/clang/3.3/lib/darwin/
export CC=/usr/local/bin/clang
export CXX=/usr/local/bin/clang++
export CFLAGS="-g3 -fsanitize=address -fsanitize=undefined"
export CXXFLAGS="-g3 -fsanitize=address -fsanitize=undefined -fno-sanitize=vptr"
./configure
Run Code Online (Sandbox Code Playgroud)
但是,这将生成一些存档警告(AR运行时)和链接错误(LD运行时)和未定义的符号.该消息类似于:
libjpeg.a(jmemmgr.o): In function `do_sarray_io':
/home/jwalton/jpeg-6b/jmemmgr.c:695: undefined reference to
`__ubsan_handle_type_mismatch'
/home/jwalton/jpeg-6b/jmemmgr.c:695: undefined reference to
`__ubsan_handle_type_mismatch'
/home/jwalton/jpeg-6b/jmemmgr.c:696: undefined reference to
`__ubsan_handle_type_mismatch'
Run Code Online (Sandbox Code Playgroud)
我知道需要链接的库.对于我使用的消毒剂,他们是libclang_rt.asan_osx.a和libclang_rt.ubsan_osx.a(或libclang_rt.full-x86_64.a和libclang_rt.ubsan-x86_64.a在Linux上).
为了提供库,我然后导出以下内容.注意:它是LIBS,而不是LDLIBS大多数其他make相关工具所预期的.
export LIBS="/usr/local/lib/clang/3.3/lib/darwin/libclang_rt.asan_osx.a \
/usr/local/lib/clang/3.3/lib/darwin/libclang_rt.ubsan_osx.a"
Run Code Online (Sandbox Code Playgroud)
这导致以下configure问题:
configure: error: cannot run C compiled programs.
If …Run Code Online (Sandbox Code Playgroud) 使用rdbuf以下方法将流复制到另一个流中是一种众所周知的方法:
#include <iostream>
#include <fstream>
int main()
{
std::ifstream in{"/tmp/foo.txt"};
std::cerr << in.rdbuf();
std::cerr << "Done\n";
}
Run Code Online (Sandbox Code Playgroud)
但是,这会中断(= 设置坏位) my cerrwhen/tmp/foo.txt为空。结果,Done\n不显示。
这是为什么?使用 G++/libstdc++/GNU Linux 和 Clang++/libc++/OS X 观察。