M. *_* E. 25 c++ function-pointers undefined-behavior c++11
关于C++标准:
std::function
GNU Compiler Collection 是否使用union
数据类型在不同的函数指针类型之间进行转换(例如,将非静态成员函数指针转换为非成员函数指针)?union
数据类型但不进行强制转换(类型擦除).undefined behavior
在不同的函数指针类型之间进行转换(在C++或C++ 11标准中)吗?我认同.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
)中读取.
n. *_* m. 10
__gnu_cplusplus_builtin_std_function__
我们所知的所有方面实施.问题的其余部分是不适定的,在评论中提到.
这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)
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/
但是,随着时间的推移,你会发现在高层次思考和建模的能力比了解特定语言的细节更重要.