小编Sam*_*ett的帖子

为您的C++库提供C API并严格别名

提供C API时的一个常见模式是在公共头中转发声明一些不透明的类型,这些类型传递给您的API方法,然后reinterpret_cast在翻译单元内转换为定义的C++类型(因此返回C++版本).

以LLVM为例:

Types.h中,声明了这个typedef:

typedef struct LLVMOpaqueContext *LLVMContextRef;
Run Code Online (Sandbox Code Playgroud)

LLVMOpaqueContext 未在项目中的任何其他位置引用.

Core.h中,声明了以下方法:

LLVMContextRef LLVMContextCreate(void);
Run Code Online (Sandbox Code Playgroud)

这是在Core.cpp中定义的:

LLVMContextRef LLVMContextCreate() {
  return wrap(new LLVMContext());
}
Run Code Online (Sandbox Code Playgroud)

wrap(和unwrap)由CBindingWrapping.h中的宏定义:

#define DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ty, ref)     \
  inline ty *unwrap(ref P) {                            \
    return reinterpret_cast<ty*>(P);                    \
  }                                                     \
                                                        \
  inline ref wrap(const ty *P) {                        \
    return reinterpret_cast<ref>(const_cast<ty*>(P));   \
}
Run Code Online (Sandbox Code Playgroud)

并在LLVMContext.h中使用:

DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LLVMContext, LLVMContextRef)
Run Code Online (Sandbox Code Playgroud)

所以我们看到C API基本上接受一个指针LLVMOpaqueContext并将其转换为一个llvm::LLVMContext对象,以执行在其上调用的任何方法.

我的问题是:这不违反严格的别名规则吗?如果没有,为什么不呢?如果是这样,那么在公共接口边界上的这种抽象如何能够合法地实现呢?

c c++ llvm strict-aliasing

25
推荐指数
1
解决办法
1759
查看次数

这是GCC的错误吗?用工会初始化结构

我可能在GCC v4.8.2中发现了一个错误,但我想在提交之前先检查一下,因为这可能是我做错了!

以下代码:

#include <vector>
struct Message
{
  typedef union {
    char byte;
    const char *str;
  } Parameter;

  Parameter p1;
  Parameter p2;
};

int main()
{
  std::vector<Message> messages_;

  messages_.push_back({{ .byte = 'a' }});

  Message message = {{ .byte = 'a' }, { .str = "Hello World" }};
  messages_.push_back(message);

  messages_.push_back({{ .byte = 'a' }, { .str = "Hello World" }});
}
Run Code Online (Sandbox Code Playgroud)

clang++ -std=c++11 main.cpp编译这个罚款.但g++输出这个:

main.cpp: In function ‘int main()’:
main.cpp:23:66: internal compiler error: in reshape_init_class, at cp/decl.c:5216
   messages_.push_back({{ …
Run Code Online (Sandbox Code Playgroud)

c++ gcc unions compiler-bug c++11

10
推荐指数
1
解决办法
694
查看次数

如何使用正则表达式找到所有Markdown链接?

在Markdown中有两种放置链接的方法,一种是只输入原始链接,例如:http://example.com,另一种是使用()[]语法:.(Stack Overflow)[http://example.com ]

我正在尝试编写一个可以匹配这两个的正则表达式,如果它是第二个匹配也捕获显示字符串.

到目前为止我有这个:

(?P<href>http://(?:www\.)?\S+.com)|(?<=\((.*)\)\[)((?P=href))(?=\])
Run Code Online (Sandbox Code Playgroud)

正则表达式可视化

Debuggex演示

但这似乎与我在Debuggex中的两个测试用例中的任何一个都不匹配:

http://example.com
(Example)[http://example.com]
Run Code Online (Sandbox Code Playgroud)

真的不确定为什么第一个不匹配,是否与我对命名组的使用有关?如果可能的话,我想继续使用,因为这是一个简化的表达式来匹配链接,在实际例子中,我觉得在同一模式中的两个不同位置复制它太长了.

我究竟做错了什么?或者这根本不可行?

编辑:我在Python中这样做,所以将使用他们的正则表达式引擎.

python regex markdown

8
推荐指数
1
解决办法
2602
查看次数

我可以拥有一个增强无锁的lambdas队列吗?

我正在尝试实现一个可以跨多个线程工作的消息传递系统.boost::lockfree::queue似乎是一个很好的方向进入,不幸的是我无法创建任何一个std::functionboost::function类型的队列,因为显然他们没有琐碎的任务和析构函数,这是一个要求boost::lockfree::queue.

我的以下代码:

#include <cassert>
//#include <functional>
#include <iostream>

#include <boost/function.hpp>
#include <boost/lockfree/queue.hpp>

int main()
{
  boost::lockfree::queue<boost::function<void(int)>> queue;
  assert(queue.is_lock_free());

  for(int j = 0; j < 50; ++j) {
    queue.push([] (int i) { std::cout << i << std::endl; });
  }

  int i = 0;
  boost::function<void(int)> functor;
  while (queue.pop(functor)) {
    functor(i++);
  }
}
Run Code Online (Sandbox Code Playgroud)

产生以下输出:

In file included from /usr/include/boost/integer.hpp:23:0,
                 from /usr/include/boost/function/function_base.hpp:21,
                 from /usr/include/boost/function/detail/prologue.hpp:17,
                 from /usr/include/boost/function.hpp:24,
                 from lockfree.cpp:5:
/usr/include/boost/lockfree/queue.hpp: In instantiation of ‘class boost::lockfree::queue<boost::function<void(int)> >’:
lockfree.cpp:10:54: …
Run Code Online (Sandbox Code Playgroud)

c++ lambda multithreading boost c++11

7
推荐指数
1
解决办法
1752
查看次数

尝试移动大型bitset时GCC4.6上出现段故障,这是编译器错误吗?

由于在bitset很大时返回了bitset的rvalue,我遇到了崩溃问题.这是一个编译器错误还是我错误地做了导致未定义行为的事情?

下面的代码在GCC 4.6.3上崩溃并-std=c++0x设置了标志.

#include <bitset>

// typedef std::bitset<0xffff> uut;
typedef std::bitset<0xffffff> uut;

struct foo {
  foo(uut b)
  : b_(std::move(b))
  {
  }

  uut b_;
};

uut make_bits(int)
{
  uut bits;

  // Only works for 0xffff:
  return std::move(bits);
  // Works for both 0xffff and 0xffffff:
  //return bits;
}

int main()
{
  foo(make_bits(0));
}
Run Code Online (Sandbox Code Playgroud)

奇怪的是,如果我删除int参数它没关系,也许这导致函数内联?

正如@unwind建议的那样,输出运行在valgrind ./a.out:

==24780== Memcheck, a memory error detector
==24780== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==24780== Using …
Run Code Online (Sandbox Code Playgroud)

c++ gcc segmentation-fault undefined-behavior move-semantics

7
推荐指数
1
解决办法
158
查看次数

我可以从类型列表中声明模板特化吗?

很确定我已经知道答案,但值得一试.

所以,说我有一个类型列表:

template <typename ...Ts>
struct typelist{};
Run Code Online (Sandbox Code Playgroud)

那包含一些对象:

struct foo{};
struct bar{};
struct quux{};

using objects = typelist<foo, bar, quux>;
Run Code Online (Sandbox Code Playgroud)

现在我有一个模板化的class(baz)可以接受任何这些对象.但是,由于代码库大小和编译时间,我希望在cpp文件中实现我的模板化方法.

所以在baz.cpp的底部,我有:

template <> class baz<foo>;
template <> class baz<bar>;
template <> class baz<quux>;
Run Code Online (Sandbox Code Playgroud)

问题是我有很多类baz,并且他们使用的对象列表也在不断变化.那么......无论如何我可以保留我的单个对象类型列表并在每个baz类似对象的cpp文件中使用它来专门化吗?然后,当我有一个新对象并且所有目标文件将重建时,我所要做的就是更新我的类型列表.

c++ templates metaprogramming template-specialization

7
推荐指数
1
解决办法
816
查看次数

使用MPL列表扩展boost变量

我正在尝试为程序提供一种向库中的变体添加新对象的方法,但我遇到了一些神秘的错误.

#include <boost/mpl/copy.hpp>
#include <boost/mpl/joint_view.hpp>
#include <boost/mpl/list.hpp>
#include <boost/variant/variant.hpp>

struct InternalType1 {};
struct InternalType2 {};

template <typename LocalTypes>
struct Foo
{
  typedef boost::mpl::list<
    InternalType1,
    InternalType2
  > Types;

  typename boost::make_variant_over<
    typename boost::mpl::joint_view<
      Types,
      LocalTypes
    >::type
  >::type container_;

  // typename boost::make_variant_over<
  //   typename boost::mpl::copy<
  //     LocalTypes,
  //     boost::mpl::back_inserter<Types>
  //   >::type
  // >::type container_;
};

struct LocalType1 {};
struct LocalType2 {};

int main()
{
  typedef boost::mpl::list<
    LocalType1,
    LocalType2
  > Types;

  Foo<Types> foo;
}
Run Code Online (Sandbox Code Playgroud)

通过使用mpl::joint_view(我假设是否是实现此目的的最有效方法),我得到以下错误:

/usr/local/include/boost/mpl/clear.hpp:29:7: error: implicit instantiation of undefined template …
Run Code Online (Sandbox Code Playgroud)

c++ boost metaprogramming boost-mpl

6
推荐指数
1
解决办法
663
查看次数

我可以基于Bool函数调用重载Haskell函数吗?

我不知道如何解释这个问题所以我只是举个例子:

-- Create a list of ints if the string contains no numbers
row :: String -> [Maybe Int]
row (isAlpha row) = [ Just $ ord c | c <- row ]
row _ = [Nothing]
Run Code Online (Sandbox Code Playgroud)

当我尝试在GHCi中加载带有此模块的模块时,我得到:

Parse error in pattern: isAlpha
Run Code Online (Sandbox Code Playgroud)

有没有办法做到这一点?或者我必须在if..else中完成所有操作?

Ninja Edit:显然,这不是一个真实的例子.我试图通过一个简单的例子来推断我所追求的行为,但事后看来这显然没有意义,因为isAlpha会返回一个Bool,而不是一个字符串所以它将是错误的参数而isAlpha无论如何都在Char not String上工作.但我只是想描绘我正在寻找的概念,所以我希望能够实现.

haskell functional-programming

5
推荐指数
1
解决办法
137
查看次数

我可以从命令行运行任意 CMake 函数吗?

我想做这样的事情:

$ cmake -E "find_package(Boost)"
Run Code Online (Sandbox Code Playgroud)

看看是成功还是失败?(即,这样我可以对项目进行一些依赖性检查,并尝试在 cmake 实际运行 CMakeLists.txt 之前安装所有这些项目。

我知道 cmake 已经有 -E 标志,但是当我运行它时,我只得到一小部分可用命令:

Usage: cmake -E [command] [arguments ...]
Available commands:
  chdir dir cmd [args]...   - run command in a given directory
  compare_files file1 file2 - check if file1 is same as file2
  copy file destination     - copy file to destination (either file or directory)
  copy_directory source destination   - copy directory 'source' content to directory 'destination'
  copy_if_different in-file out-file  - copy file if input has changed
  echo [string]... …
Run Code Online (Sandbox Code Playgroud)

cmake

4
推荐指数
1
解决办法
2637
查看次数

如果不同的线程总是使用不同的键,它们可以插入到映射中吗?

我正在尝试为一个对象设计一个消息队列。有一组 X 线程都可以向该对象发送消息(稍后处理)。如果我有一个std::map<thread_id_t, message>,这个线程安全吗?假设线程 1 仅添加密钥为 1 的消息,线程 2 添加到密钥 2 等消息?

c++ multithreading std thread-safety

3
推荐指数
1
解决办法
3637
查看次数