gcc deep/double/nested casting - c++

First is the code
#include <stdio.h>
typedef wchar_t* BSTR;
wchar_t hello[] = L"Hello";
class _bstr_t {
public:
operator const wchar_t*() const throw() { return hello; }
operator wchar_t*() const throw() { return hello; }
};
class container {
public:
operator _bstr_t() { return _bstr_t(); }
};
int main()
{
// This gives error (with gcc 4.5.2 at least):
// test.cpp:20:27: error: cannot convert "container" to "wchar_t*" in initialization
wchar_t *str = container();
printf("%S\n", str);
return 0;
}
The problem here is that container() can be casted to _bstr_t and then to wchar_t*, but, gcc does not.
The problem can be solved using manual cast:
wchar_t *str = (_bstr_t)container();
But what I need is to avoid manual cast, I would like gcc to figure this out automatically.
Why I need this is because the returned container type objects will be used in calls like
void Func(wchar_t* str);
Func(myObject->Container);
where I don't want to do manual casting.
I verified Visual Studio and it does not seem to support such scenario, too. Too bad, but I would be glad if someone can provide a workaround, even if for this specific case.
UPDATE: for those who suggests operator wchar_t* on the container, that was the problem in first place. This will either leak or crash when destroyed before Func() has a chance to accept the pointer.

When doing implicit conversions, there's at most one user-defined conversion that can happen. MSVC behaviour is not standard compliant in this matter.
C++11 (12.3 Conversions):
At most one user-defined conversion (constructor or conversion function) is implicitly applied to a single value.
For the implicit conversion to work, container has to convert directly to wchar_t*.

It doesn't work because the class container has no operator wchar_t*(). The only solution is to add it to the container class :
#include <iostream>
typedef wchar_t* BSTR;
wchar_t hello[] = L"Hello";
class container {
public:
operator const wchar_t*() const throw() { return hello; }
operator wchar_t*() const throw() { return hello; }
};
int main()
{
// This gives error (with gcc 4.5.2 at least):
// test.cpp:20:27: ошибка: cannot convert «container» to «wchar_t*» in initialization
wchar_t *str = container();
std::wcout<<str<<std::endl;
}

You do not have a converter from wchar_t * to container that is why you get the error
class container {
public:
operator wchar_t*() { return _bstr_t(); }
};

Related

How can I decay const char that is passed as reference to a function with variadic parameters?

I have a function like this:
void column(const std::string &value) { ... }
void column(float value) { ... }
template <class... TColumns> void row(const TColumns &...columns) {
ImGui::TableNextRow();
(column(columns), ...);
}
I am using clang-tidy static analyzer to make sure that my code is always compliant with cpp core guidelines. I am using this function in the following way:
// (const char[5], float)
row("Hello", 20.5f);
My understanding is that, std:string accepts const char * but the first argument of the function call above gets inferred to const char[5]. This causes array decay and I get clang-tidy error that:
do not implicitly decay an array into a pointer; consider using gsl::array_view or an explicit cast instead
Is it possible to somehow enforce that string argument that is passed is always const char *, not const char[5] or const char[6] etc?
Since you anyways convert a c-string to a string each time you reach this line, it's suggested to have a static string. That is expected to solve the warning as well.
#include <iostream>
void column(const std::string &value) { }
void column(float value) { }
template <class... TColumns> void row(const TColumns &...columns) {
// ...
(column(columns), ...);
}
int main() {
static auto hello = std::string{"Hello"};
row(hello, 20.5f);
}
However, the best solution is likely to simply turn off the warning - either globally, or as Drew wrote, via // NOLINT.

Variadic arguments (va_arg) and its default type

When I use printf to print a std::string on the screen I need to use "%s" and c_str() function. I'd like to create a class that inherits from std::string and by default returns value of c_str like in the example below:
class String : public std::string
{
public:
using std::string::string;
operator const char *() const
{
return c_str();
}
};
...
String s = "abc";
printf("%s\n", abc);
It won't work as operator const char *() is not applied for the type of ... that is used in printf function. Any ideas how to do this? const void *' doesn't work either.

Best interface to create a resource and return it to be released by the caller

I have a char* array that is new'd and initialized in a function. Normally I'd use std::string but the array is null terminated with possibly more than one '\0' and I would like to capture the full size.
As it is, the Caller must remember to delete[] the char * when it uses this function. I'd like to clean up the interface so that delete[] is called in a destructor when it goes out of scope but I'm unsure of what to use. Is there a smart pointer than can take a char *?
Edit:
Id rather not use std::string as it would be unclear that this isnt a C-style null terminated string. Can I use a boost::scoped_array<char> for this? Since scoped_array is non-copyable how would I return it from the function that created it?
This is what OO programming is all about. Use std::string like comment above, or create a class that handles the data for you:
class MyObj {
private:
char *data;
int len;
public:
MyObj( const char *data, int len ) {
this->data = new char[...
// do what you need here
}
const char* getStr() const {
return data;
}
int getLen() const {
return len;
}
~MyObj() {
delete [] data;
}
};
You'll probably also want to implement copy constructor and assignment operator (or privatize their use)...
Alternatively, use std::string as your base implementation but only expose what and how you want:
class MyObj : private std::string {
public:
// whatever you want here
const char* data() {
return c_str();
}
int length() const {
return std::string::length();
}
};
Before 2011, your choices for returning a dynamic array from a function were std::string, std::vector<char> or boost::shared_array<char>. With a modern implementation, you could also use std::unique_ptr<char[]>.
I'd recommend using std::string to represent a string.

Is it possible to have a C++ method accept either const char* and const wchar_t* as a parameter without overloading the method?

UPDATE:
I went for the template approach cause it seemed the most elegant / concise but then I end up with stuff like this:
template<typename charType>
int doSomethingWithString(const charType* buffer)
{
wchar_t* tempBuffer = NULL;
if(typeid(charType) == typeid(char))
{
tempBuffer = (wchar_t*)malloc(sizeof(wchar_t)*strlen((char*)buffer));
mbstowcs(tempBuffer, (const char*)buffer, strlen((const char*)buffer));
}
else if(typeid(charType) == typeid(wchar_t))
{ tempBuffer = (wchar_t*)malloc(sizeof(wchar_t)*strlen((char*)buffer));
tempBuffer = wcscpy(tempBuffer, (const wchar_t*)buffer);
}
At which point I feel it's kind of ugly (specially since I still have to have all those casts there to let the compiler know). I also tried turning the parameter into a wstring but I just don't seem to find an appropriate constructor for both cases?
It's been a while now that I've been away from C++ and I can't remember the C++ way of going about this:
Let's say I have a class with some method myClass::doSomethingWithString(...) and I want the same method to be able to be called passing in a character sequence as either const char* or const wchar_t*. Was there a way to make the method be able to accept both types of "strings" and tell if the parameter is const char* or const wchar_t* inside the method implementation? Or is method overloading the only way to go about it?
Method overloading is the only way to go about it.
Alternately, You could write a single template function.However, in that case the actions you perform inside the function would have to be same in either case. In this case the compiler will generate source code of the functions for your both the types.
Overloading is probably the best way to go about it, unless you're using another API that allows exactly the same syntax with both char* and wchar_t*.
void foo(char const *c) {
std::cout << c << '\n';
}
void foo(wchar_t const *c) {
std::wcout << c << L'\n';
}
You could also use templates. If the code doesn't actually change between char and wchar_t versions then you'll only have one version:
template<typename CharT>
void foo(CharT const *c) {
std::cout << "foo called\n";
}
But since doing anything useful usually involves using the argument, and using the argument usually requires different code (e.g. calling printf for char and wprintf for wchar_t) you'll have to have a version for each type. With a template you'd do that by specializing.
template<typename CharT>
void foo(CharT const *c);
template<> void foo<char>(char const *c) { /* char version */ }
template<> void foo<wchar_t>(wchar_t const *c) { /* wchar_t version */ }
Now, if you have an API that provides an identical interface for wchar_t and char via overloading or specializing, then templates let you build on top of that by having a single version for both types using the overloaded API:
// Given the above overloads/template specializations:
template<typename CharT>
void bar(CharT const *c) {
foo(c); // calls foo(char const *) or foo(wchar_t const *) as needed.
}
But since you're asking if there's a way to tell inside the function what the type is, it seems likely that you want to have different versions. In which case you're probably best off using overloads, or factoring the differences out into overloaded functions so the main function can be a single template.
There is another option that's probably a bad idea. Depending on the actual differences you might be able to have a single template and then do something like:
template<typename T>
int foo(T const *t) {
if(sizeof T == sizeof wchar_t) {
// wchar_t version
} else {
// char version
}
}
And someday C++ may adopt static_if in which case you'll be able to do:
template<typename T>
int foo(T const *t) {
static_if(std::is_same<T,wchar_t>::value) {
// wchar_t version
}
static_if(std::is_same<T,char>::value) {
// char version
}
}
char and wchar_t are different types, so are the pointers to them. Thus you cannot write one function that accepts both as there is no common "parent" (so to speak).
YOu can write a template function that accepts the type as a template parameter. In that case you still have two functionsin your binary program if you call it both with char* and wchar_t*, but in the cose you will see only one function body.
template<T> void someFunction(T* str) {
// your code here. Use T when you would use char or wchar_t in a regular function
}
You can use method overloading. I would also suggest using std::string and std::wstring for C++.
Example:
class MyClass
{
public:
void doSomethingWithString(std::string s)
{
std::cout << "String: " << s << std::endl;
}
void doSomethingWithString(std::wstring ws)
{
std::wcout << L"Wide String: " << ws << std::endl;
}
};
...
MyClass myClass;
myClass.doSomethingWithString("const char *");
myClass.doSomethingWithString(L"const wchar_t *");
Write a class that has implicit constructors for both kinds of arguments:
struct String {
String(const char*): called_with_wchar_t(false) { }
String(const wchar_t*): called_with_wchar_t(true) { }
bool called_with_wchar_t;
};
void function(const String&);
...
function("a");
function(L"a");
Or use Boost.Variant.

Why is "operator bool()" invoked when I cast to "long"?

I have the following class:
class MyClass {
public:
MyClass( char* what ) : controlled( what ) {}
~MyClass() { delete[] controlled; }
operator char*() const { return controlled; }
operator void*() const { return controlled; }
operator bool() const { return controlled != 0; }
private:
char* controlled;
};
This is compiled with Microsoft SDK that has the following typedefs:
typedef long LONG_PTR;
typedef LONG_PTR LPARAM;
The calling code does the following:
MyClass instance( new char[1000] );
LPARAM castResult = (LPARAM)instance;
// Then we send message intending to pass the address of the buffer inside MyClass
::SendMessage( window, message, wParam, castResult );
Suddenly castResult is 1 - MyClass::operator bool() is invoked, it returns true which is converted to 1. So instead of passing the address I pass 1 into SendMessage() which leads to undefined behaviour.
But why is operator bool() invoked in the first place?
It's one of the known pitfalls of using operator bool, that is a aftershock of C inheritance. You'd definitively benefit from reading about the Safe Bool Idiom.
In general, you didn't provide any other matchable casting operator, and bool (unfortunately) is treated as a good source for arithmetic casting.
operator bool is the best match, because char* and void* can't be converted to long without an explicit cast, unlike bool:
long L1 = (void*)instance; // error
long L2 = (char*)instance; // error
long L3 = (bool)instance; // ok
You cannot implicitly cast a T* to long. But you can cast a bool to long.
So the operator bool is used.
You have to define a operator LPARAM.