Kim*_*bel 51 c c++ namespaces c-preprocessor
有没有办法(ab)使用C预处理器来模拟C中的命名空间?
我正在考虑以下几点:
#define NAMESPACE name_of_ns
some_function() {
some_other_function();
}
Run Code Online (Sandbox Code Playgroud)
这将被翻译为:
name_of_ns_some_function() {
name_of_ns_some_other_function();
}
Run Code Online (Sandbox Code Playgroud)
ram*_*ion 82
另一种方法是声明一个struct来保存你的所有函数,然后静态地定义你的函数.然后,您只需要担心全局名称struct的名称冲突.
// foo.h
#ifndef FOO_H
#define FOO_H
typedef struct {
int (* const bar)(int, char *);
void (* const baz)(void);
} namespace_struct;
extern namespace_struct const foo;
#endif // FOO_H
// foo.c
#include "foo.h"
static int my_bar(int a, char * s) { /* ... */ }
static void my_baz(void) { /* ... */ }
namespace_struct const foo = { my_bar, my_baz }
// main.c
#include <stdio.h>
#include "foo.h"
int main(void) {
foo.baz();
printf("%d", foo.bar(3, "hello"));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在上面的例子中,my_bar
并my_baz
不能直接从main.c调用,只能通过foo
.
如果您有一堆声明具有相同签名的函数的命名空间,那么您可以标准化该集合的命名空间结构,并选择在运行时使用哪个命名空间.
// goo.h
#ifndef GOO_H
#define GOO_H
#include "foo.h"
extern namespace_struct const goo;
#endif // GOO_H
// goo.c
#include "goo.h"
static int my_bar(int a, char * s) { /* ... */ }
static void my_baz(void) { /* ... */ }
namespace_struct const goo = { my_bar, my_baz };
// other_main.c
#include <stdio.h>
#include "foo.h"
#include "goo.h"
int main(int argc, char** argv) {
namespace_struct const * const xoo = (argc > 1 ? foo : goo);
xoo->baz();
printf("%d", xoo->bar(3, "hello"));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
多个定义my_bar
并且my_baz
不冲突,因为它们是静态定义的,但是底层函数仍然可以通过适当的命名空间结构访问.
Chr*_*oph 49
使用名称空间前缀时,我通常会为缩短的名称添加宏,这些名称可以#define NAMESPACE_SHORT_NAMES
在包含标题之前激活.标题foobar.h可能如下所示:
// inclusion guard
#ifndef FOOBAR_H_
#define FOOBAR_H_
// long names
void foobar_some_func(int);
void foobar_other_func();
// short names
#ifdef FOOBAR_SHORT_NAMES
#define some_func(...) foobar_some_func(__VA_ARGS__)
#define other_func(...) foobar_other_func(__VA_ARGS__)
#endif
#endif
Run Code Online (Sandbox Code Playgroud)
如果我想在包含文件中使用短名称,我会这样做
#define FOOBAR_SHORT_NAMES
#include "foobar.h"
Run Code Online (Sandbox Code Playgroud)
我发现这比使用Vinko Vrsalovic所描述的命名空间宏(在评论中)更清晰,更有用.
Meh*_*ari 13
你可以使用##运算符:
#define FUN_NAME(namespace,name) namespace ## name
Run Code Online (Sandbox Code Playgroud)
并将函数声明为:
void FUN_NAME(MyNamespace,HelloWorld)()
Run Code Online (Sandbox Code Playgroud)
看起来很尴尬.
我想出了以下方案:
(标题)
// NS_PREFIX controls the prefix of each type and function declared in this
// header, in order to avoid name collision.
#define NS_PREFIX myprefix_
// Makes a string from argument (argument is not macro-expanded).
#define stringify(arg) #arg
// Concatenation that macro-expands its arguments.
#define concat(p1, p2) _concat(p1, p2) // Macro expands the arguments.
#define _concat(p1, p2) p1 ## p2 // Do the actual concatenation.
// Append the namespace prefix to the identifier.
#define ns(iden) concat(NS_PREFIX, iden)
// header content, for instance :
void ns(my_function)(int arg1, ns(t) arg2, int arg3);
// Allow implementation files to use namespacing features, else
// hide them from the including files.
#ifndef _IMPL
#undef NS_PREFIX
#undef ns
#undef stringify
#undef concat
#undef _concat
#endif // _IMPL
Run Code Online (Sandbox Code Playgroud)
(实现)
#define _IMPL
#include "header.h"
#undef __IMPL
Run Code Online (Sandbox Code Playgroud)
小智 5
我使用基于结构的方法,并进行了两个改进:添加子结构以创建分层名称空间,并且当我想简化名称空间的路径时定义一些简单的宏。
让我们以Foobar库为例。
foobar.h
#ifndef __FOOBAR_H__
#define __FOOBAR_H__
// definition of the namespace's hierarchical structure
struct _foobar_namespace {
struct {
void (*print)(char *s);
} text;
struct {
char *(*getDateString)(void);
} date;
};
// see the foobar.c file
// it must be the only one defining the FOOBAR macro
# ifndef FOOBAR
// definition of the namespace global variable
extern struct _foobar_namespace foobar;
# endif // FOOBAR
#endif // __FOOBAR_H__
Run Code Online (Sandbox Code Playgroud)
foobar.c
// the FOOBAR macro is needed to avoid the
// extern foobar variable declaration
#define FOOBAR
#include "foobar.h"
#include "foobar_text.h"
#include "foobar_date.h"
// creation of the namespace global variable
struct _foobar_namespace foobar = {
.text = {
.print = foobar_text__print
},
.date = {
.getDateString = foobar_date__getDateString
}
};
Run Code Online (Sandbox Code Playgroud)
然后,可以使用名称空间:
#include "foobar.h"
void main() {
foobar.text.print("it works");
}
Run Code Online (Sandbox Code Playgroud)
但是foobar_text__print()
和之间没有太大区别foobar.text.print()
。我认为第二个更具可读性,但是值得怀疑。因此,通过定义一些宏来简化这些名称空间将变得非常有用:
#include "foobar.h"
#define txt foobar.text
#define date foobar.date
void main() {
char *today = date.getDateString();
txt.print(today);
}
Run Code Online (Sandbox Code Playgroud)
这种分层的名称空间可以快速定义,易于理解并减少代码的冗长性。
只是为了好玩,这里是foobar.text
代码文件:
foobar_text.h
#ifndef __FOOBAR_TEXT_H__
#define __FOOBAR_TEXT_H__
void foobar_text__print(char *s);
#endif // __FOOBAR_TEXT_H__
Run Code Online (Sandbox Code Playgroud)
foobar_text.c
#include <stdio.h>
#include "foobar_text.h"
void foobar_text__print(char *s) {
printf("%s\n", s);
}
Run Code Online (Sandbox Code Playgroud)
我写了一篇关于如何使用 C 来利用命名空间和/或模板的教程。
对于基本命名空间,可以简单地为命名空间名称添加前缀作为约定。
namespace MY_OBJECT {
struct HANDLE;
HANDLE *init();
void destroy(HANDLE * & h);
void do_something(HANDLE *h, ... );
}
Run Code Online (Sandbox Code Playgroud)
可以写成
struct MY_OBJECT_HANDLE;
struct MY_OBJECT_HANDLE *my_object_init();
void my_object_destroy( MY_OBJECT_HANDLE * & h );
void my_object_do_something(MY_OBJECT_HANDLE *h, ... );
Run Code Online (Sandbox Code Playgroud)
我需要的第二种使用命名空间和模板概念的方法是使用宏串联和包含。例如,我可以创建一个
template<T> T multiply<T>( T x, T y ) { return x*y }
Run Code Online (Sandbox Code Playgroud)
使用模板文件如下
乘法模板.h
_multiply_type_ _multiply_(multiply)( _multiply_type_ x, _multiply_type_ y);
Run Code Online (Sandbox Code Playgroud)
乘法模板.c
_multiply_type_ _multiply_(multiply)( _multiply_type_ x, _multiply_type_ y) {
return x*y;
}
Run Code Online (Sandbox Code Playgroud)
我们现在可以定义 int_multiply 如下。在此示例中,我将创建一个 int_multiply.h/.c 文件。
int_multiply.h
#ifndef _INT_MULTIPLY_H
#define _INT_MULTIPLY_H
#ifdef _multiply_
#undef _multiply_
#endif
#define _multiply_(NAME) int ## _ ## NAME
#ifdef _multiply_type_
#undef _multiply_type_
#endif
#define _multiply_type_ int
#include "multiply-template.h"
#endif
Run Code Online (Sandbox Code Playgroud)
int_multiply.c
#include "int_multiply.h"
#include "multiply-template.c"
Run Code Online (Sandbox Code Playgroud)
最后,您将获得一个函数和头文件。
int int_multiply( int x, int y ) { return x * y }
Run Code Online (Sandbox Code Playgroud)
我根据提供的链接创建了一个更详细的教程。希望这对某人有帮助!
归档时间: |
|
查看次数: |
48833 次 |
最近记录: |