为什么此代码在 C-stdio 函数重载上表现不同? (vfprintf 与 putchar)
Why does this code behave differently on C-stdio function overloads? (vfprintf vs. putchar)
我正在尝试定义各种与 C stdio 同名的函数,以防止不必要的使用。我遇到了一种奇怪的情况,该技术适用于某些功能,但不适用于其他功能。我无法解释为什么 A::fn
调用 vfprintf
的 stdio 版本而不是 A
命名空间中的函数定义。
#include <stdio.h>
#include <stdarg.h>
namespace A {
template <typename... Ts>
void putchar(int ch) {
static_assert(sizeof...(Ts) == -1);
}
template <typename... Ts>
void vfprintf(FILE* file, const char* fmt, va_list vlist) {
static_assert(sizeof...(Ts) == -1);
}
void fn(const char* fmt, ...)
{
putchar('A'); // fails to compile (as expected)
va_list vlist;
va_start(vlist, fmt);
vfprintf(stdout, "Hello!\n", vlist); // does not fail (not expected)
va_end(vlist);
}
}
int main()
{
A::fn("hello");
return 0;
}
P.S。很高兴听到评论表明有更好的方法来限制 C 风格 I/O(也许是 clang-tidy)。
替换标准库例程是 UB(引文如下)。请参阅示例 here and here 了解这可能导致的问题类型。
编辑: 好的,这是承诺的 citation:
The C++ standard library reserves the following kinds of names:
...
names with external linkage
...
If a program declares or defines a name in a context where it is reserved, other than as explicitly allowed by [library], its behavior is undefined.
但是,正如评论中所讨论的那样,我不确定您是否在允许的上下文中执行此操作(尽管经过深思熟虑,我认为您不是),所以我要改变策略。
事实上,有一种非常简单的方法可以满足您的需求。您可以使用 #pragma GCC poison
执行此操作。因此,以您的示例为例,您只需要:
#pragma GCC poison putchar vfprintf
大功告成。 clang 也支持这个编译指示。
帽子,兔子,我们都能搞定:)(天气好的时候)
我正在尝试定义各种与 C stdio 同名的函数,以防止不必要的使用。我遇到了一种奇怪的情况,该技术适用于某些功能,但不适用于其他功能。我无法解释为什么 A::fn
调用 vfprintf
的 stdio 版本而不是 A
命名空间中的函数定义。
#include <stdio.h>
#include <stdarg.h>
namespace A {
template <typename... Ts>
void putchar(int ch) {
static_assert(sizeof...(Ts) == -1);
}
template <typename... Ts>
void vfprintf(FILE* file, const char* fmt, va_list vlist) {
static_assert(sizeof...(Ts) == -1);
}
void fn(const char* fmt, ...)
{
putchar('A'); // fails to compile (as expected)
va_list vlist;
va_start(vlist, fmt);
vfprintf(stdout, "Hello!\n", vlist); // does not fail (not expected)
va_end(vlist);
}
}
int main()
{
A::fn("hello");
return 0;
}
P.S。很高兴听到评论表明有更好的方法来限制 C 风格 I/O(也许是 clang-tidy)。
替换标准库例程是 UB(引文如下)。请参阅示例 here and here 了解这可能导致的问题类型。
编辑: 好的,这是承诺的 citation:
The C++ standard library reserves the following kinds of names:
...
names with external linkage
...
If a program declares or defines a name in a context where it is reserved, other than as explicitly allowed by [library], its behavior is undefined.
但是,正如评论中所讨论的那样,我不确定您是否在允许的上下文中执行此操作(尽管经过深思熟虑,我认为您不是),所以我要改变策略。
事实上,有一种非常简单的方法可以满足您的需求。您可以使用 #pragma GCC poison
执行此操作。因此,以您的示例为例,您只需要:
#pragma GCC poison putchar vfprintf
大功告成。 clang 也支持这个编译指示。
帽子,兔子,我们都能搞定:)(天气好的时候)