我们有时必须根据C++标准编写具有未定义行为的代码吗?

M. *_* E. 25 c++ function-pointers undefined-behavior c++11

关于C++标准:

  1. std::functionGNU Compiler Collection 是否使用union数据类型在不同的函数指针类型之间进行转换(例如,将非静态成员函数指针转换为非成员函数指针)?我认同. 编辑:它使用union数据类型但不进行强制转换(类型擦除).
  2. 它是undefined behavior在不同的函数指针类型之间进行转换(在C++或C++ 11标准中)吗?我认同.
  3. 是否可以在std::function不使用任何具有undefined behavior?的代码的情况下实现?我不这么认为.我在说这个.

以下是我的问题:

我们有时必须编写undefined behavior符合C++标准的代码(但它们defined behavior适用于特定的C++编译器,如GCC或MSVC)?

这是否意味着我们不能/不应该阻止undefined behavior我们的C++代码?

Mat*_*lia 41

没有人强迫你写任何东西,所以没有人强迫你编写调用UB的代码.

至于标准库,它的代码可以自由地包含它想要的任何非便携行为 - 哎呀,它甚至可以用另一种语言编写,编译器通过神奇的独角兽创建绑定; 重要的是它的行为符合规范.

想想看,很明显,在某种程度上标准库必须超出标准 - 制作系统调用,与硬件交谈,......标准甚至没有考虑到,并且通常是特定于平台的.例如,在64位Linux上,您可以使用内联汇编(通过sysenter指令)执行系统调用- 标准不禁止此操作,它只是不强制要求每个平台都必须像这样.

至于具体的例子,我没有看到任何UB - union标准规定使用的s - 即只从您写入的最后一个成员(因此字段m_flag)中读取.

  • 为创造标准的神奇独角兽+1. (10认同)

n. *_* m. 10

  1. 为什么这有趣?它可以根据__gnu_cplusplus_builtin_std_function__我们所知的所有方面实施.
  2. 不,标准明确允许这样做.
  3. 绝对是的,有许多完全符合标准的技术.

问题的其余部分是不适定的,在评论中提到.

std::function是一个信封背面的基本模型,没有演员或工会或AFAICT任何远程危险的东西.当然不是所有的真实特征std::function,但这只是一些技术工作的问题.

#include <memory>
#include <iostream>
#include <type_traits>

template <typename R, typename ... Args>
struct CallBase
{
  virtual R operator()(Args... args) = 0;
  virtual ~CallBase() {}
};

template <typename R, typename ... Args>
struct FunCall : CallBase<R, Args...>
{
  virtual R operator()(Args... args) { return f(args...); }
  R(*f)(Args...);
  FunCall(R f(Args...)) : f(f) {}
};

template <typename Obj, typename R, typename ... Args>
struct ObjCall : CallBase<R, Args...>
{
  virtual R operator()(Args... args) { return o(args...); }
  Obj o;
  ObjCall(Obj o) : o(o) {}
};

template <typename R, typename ... Args> struct MemFunCall;
template <typename R, typename Cl, typename ... Args>
struct MemFunCall<R, Cl, Args...> : CallBase<R, Cl, Args...>
{
  typedef typename std::remove_reference<Cl>::type Rcl;
  virtual R operator()(Cl c, Args... args) { return (c.*f)(args...); }
  R (Rcl::*f)(Args...);
  MemFunCall(R (Rcl::*f)(Args...)) : f(f) {}
};


template <typename Fn> class Function;
template <typename R> struct Function<R()>
{
  std::unique_ptr<CallBase<R>> fn;
  R operator()() { return (*fn)(); }
  Function(R (*f)()) : fn(new FunCall<R>(f)) {}
  template<typename Obj>
  Function(Obj o) : fn(new ObjCall<Obj, R>(o)) {}
};

template <typename R, typename Arg1, typename ... Args> 
struct Function<R(Arg1, Args...)>
{
  std::unique_ptr<CallBase<R, Arg1, Args...>> fn;
  R operator()(Arg1 arg1, Args... args) { return (*fn)(arg1, args...); }
  Function(R (*f)(Arg1 arg1, Args...)) :
    fn(new FunCall<R, Arg1, Args...>(f)) {}
  template<typename T>
  Function(R (T::*f)(Args...)) : 
    fn(new MemFunCall<R, Arg1, Args...>(f)) {}
  template<typename Obj>
  Function(Obj o) : fn(new ObjCall<Obj, R, Arg1, Args...>(o)) {}
};

struct Foo
{
  static void bar (int a) { std::cout << "bar " << a << std::endl; }
  int baz (const char* b) { std::cout << "baz " << b << std::endl; return 0; }
  void operator()(double x) { std::cout << "operator() " << x << std::endl; }

};

int main ()
{
  Function<void(int)> f1(&Foo::bar);
  f1(3);
  Foo foo;
  Function<int(Foo&, const char*)> f2(&Foo::baz);
  f2(foo, "whatever");
  Function<void(double)> f3(foo);
  f3(2.75);
}
Run Code Online (Sandbox Code Playgroud)


use*_*108 5

GNU Compiler Collection的std :: function是否使用union数据类型在不同的函数指针类型之间进行转换(例如,将非静态成员函数指针转换为非成员函数指针)?我认同.

不,它使用类型擦除.它是一种variant用于功能对象的.

在不同的函数指针类型之间(在C++或C++ 11 Standard中)是否存在未定义的行为?我认同.

它不一定是,你可以将一个函数指针转换为另一个函数指针,并将成员函数指针转换为另一个成员函数指针.

是否可以在不使用任何具有未定义行为的代码的情况下实现std :: function?我不这么认为.我在说这个.

是的,你可以,有很多例子,这很容易,这样做会教你很多关于c ++的知识:

http://probablydance.com/2013/01/13/a-faster-implementation-of-stdfunction/ https://codereview.stackexchange.com/questions/14730/impossibly-fast-delegate-in-c11 http:/ /avdgrinten.wordpress.com/2013/08/07/c-stdfunction-with-the-speed-of-a-macro/

但是,随着时间的推移,你会发现在高层次思考和建模的能力比了解特定语言的细节更重要.