在支持多种类型的宏中使用printf

using printf in a macro supporting multiple types

本文关键字:printf 支持 种类 类型      更新时间:2023-10-16

我有一个宏:

#define assert_cmp(a, cmp, b) 
    if(!((a) cmp (b))) { 
        std::cerr << "Assertion failed: " << a << " " << #cmp << " " << b << std::endl; 
        assert((a) cmp (b)); 
    }

(是的,我也许应该围绕它做do { ... } while(0) ...(

然后我可以使用它,例如:

void f(int a) {
    assert_cmp(a, <=, 42);
    // ...
}

正常工作。但是,现在,我也想对一些CUDA代码使用相同的宏,并且我只能在那里使用printf。(CUDA与问题并不相关,只是我必须使用printf。(

如何将宏转换为使用printf而不是std::cerr?这并不是那么简单,因为参数 ab可以是任何类型的(尽管我们现在只关心数字类型是可以的(。

也许喜欢:

#define assert_cmp(a, cmp, b) 
    if(!((a) cmp (b))) { 
        printf("Assertion failed: "); 
        printf(_format_for_type(a), a); 
        printf(" " #cmp " "); 
        printf(_format_for_type(b), b); 
        printf("n"); 
        assert((a) cmp (b)); 
    }
template<typename T>
const char* _format_for_type(const T&);
template<> const char* _format_for_type(const int&) { return "%i"; }
template<> const char* _format_for_type(const float&) { return "%f"; }
...

如何翻译宏以使用printf代替std :: cerr?

这是一般不可能做的,因为printf仅支持有限的指定符和长度子分类器计数。换句话说,可以用operator<<打印类型,但不能用printf

您可以做std::ostringstream ss; ss << stuff; printf("%s", ss.str());

也许喜欢:

是的,这样,这是一种很好的方法,可以控制和在编译时检测到任何问题。我认为创建格式字符串的价值没有,只需打印值即可。我不会创建格式字符串,而只是输出值,这将允许为自定义类型创建过载。

template<typename T> void myprint(const T&);
template<> void myprint(const int& v) { printf("%i", v); }
template<> void myprint(const float& v) { printf("%f", v); }
// custom types
class MyData {
    int a;
    int b;
    template<typename T> friend void myprint(const T &v);
};
template<> void myprint(const MyData& v) {
    printf("%d %d", v.a, v.b);
}
#define assert_cmp(a, cmp, b) 
    ... myprint(a); ...