C ++:传递类可变参数函数 [英] C++: Passing classes to vararg function
问题描述
我试图做一个行为像MS的CString类(也就是你将它传递给printf和它的行为就像一个指针,C字符串,而无需额外丑陋的黑魔法,如.c_str())。
I'm trying to make a class that behaves like MS CString (that is, you pass it to printf and it acts just like a pointer to C string, without additional ugly black magic like ".c_str()").
这是第一个实施这一类的,那只是工作,并且未提供任何有用的:
This is very first implementation of this class, that just works and doesn't yet provide anything useful:
#include <cstdlib>
#include <cstring>
class CString
{
protected:
struct CStringInfo
{
size_t Length;
size_t MaxLength;
};
public:
CString()
{
Buffer = NULL;
Assign(NULL);
}
CString(const char* chv)
{
Buffer = NULL;
Assign(chv, 0);
}
~CString()
{
if(Buffer) delete[] Buffer;
Buffer = NULL;
}
size_t GetLength()
{
if(!Buffer) Alloc(1);
return GetInfo()->Length;
}
size_t Resize(size_t size)
{
Alloc(size + 1); // + 0x00
Buffer[size] = 0;
return size;
}
bool Assign(const char* value, size_t size = 0)
{
size_t strl = ((size) ? size : strlen(value));
if(!value || !(strl = strlen(value)))
{
if(!Buffer) Alloc(1);
return false;
}
Alloc(strl + 1);
memcpy(Buffer, value, strl);
Buffer[strl] = 0;
return true;
}
CString& operator = (const char* what)
{
Assign(what);
return (*this);
}
CString& operator = (CString& string)
{
Assign(string.Buffer);
return (*this);
}
operator const char* ()
{
return Buffer;
}
protected:
char* Buffer;
void Alloc(size_t size)
{
if(!size) size = 1;
char* nb = new char[size + sizeof(CStringInfo)];
char* nbb = nb + sizeof(CStringInfo);
size_t cl = size - 1;
if(Buffer)
{
if(cl > GetInfo()->Length) cl = GetInfo()->Length;
if(cl) memcpy(nbb, Buffer, cl - 1);
nbb[cl] = 0;
*(CStringInfo*)(nb) = *(CStringInfo*)(Buffer);
delete[] (Buffer - sizeof(CStringInfo));
}
Buffer = nb;
GetInfo()->MaxLength = size;
GetInfo()->Length = cl;
}
void Free()
{
if(Buffer)
{
delete[] (Buffer - sizeof(CStringInfo));
}
}
CStringInfo* GetInfo()
{
return (CStringInfo*)(this->Buffer - sizeof(CStringInfo));
}
};
和code我测试它:
#include <cstdio>
#include "CString.hpp"
CString global_str = "global string!";
int main(int argc, char* argv[])
{
CString str = "string";
printf("Test: %s, %s\n", str, global_str);
return 0;
}
如果我没有在类析构函数,那么我可以将它传递给printf和它的工作就像它应该(为C字符串)。但是,当我加入析构函数,GCC会产生以下错误:
If I don't have a destructor in the class, then I can pass it to printf and it will work just like it should (as a C string). But when I add destructor, GCC produces following error:
error: cannot pass objects of non-trivially-copyable type 'class CString' through '...'
和除海湾合作委员会的事先版本将给予警告+ UD2运code。
And in addition to that prior versions of GCC will give a warning + ud2 opcode.
所以......提问:其实我可以做以下的建设工作在GCC或者有没有什么办法,可能不涉及Ç可变参数,使一些在使用中与上面code
So... Question: can I actually make following construction work in GCC or is there any way, possibly not involving C varargs, to make something identical in use to above code?
推荐答案
您可以用投触发转换操作符:
You can trigger the conversion operator with a cast:
printf("Test: %s, %s\n", static_cast<const char*>(str),
static_cast<const char*>(global_str));
不过,我不知道你是否会遇到这种任何问题,避免在C ++中code可变参数可能会是最好的。
However, I don't know if you will run into any problems with this, avoiding varargs in C++ code would probably be the best.
如何使用类型安全的printf ,而不是(来源:维基百科):
How about using the type-safe printf instead (Credit: Wikipedia):
void printf(const char *s)
{
while (*s) {
if (*s == '%') {
if (*(s + 1) == '%') {
++s;
}
else {
throw std::runtime_error("invalid format string: missing arguments");
}
}
std::cout << *s++;
}
}
template<typename T, typename... Args>
void printf(const char *s, T value, Args... args)
{
while (*s) {
if (*s == '%') {
if (*(s + 1) == '%') {
++s;
}
else {
std::cout << value;
printf(s + 1, args...); // call even when *s == 0 to detect extra arguments
return;
}
}
std::cout << *s++;
}
throw std::logic_error("extra arguments provided to printf");
}
我不认为的libstdc ++支持的std :: runtime_error
和的std :: logic_error
虽然
这篇关于C ++:传递类可变参数函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!