Space in Function Call Parameter List (C++) - c++

I came across some syntax in a C++ project I'm working with and do not know what to make of it. The compiler does not throw any errors in relation to this:
lua_pushstring(L,"swig_runtime_data_type_pointer" SWIG_RUNTIME_VERSION SWIG_TYPE_TABLE_NAME);
Notice the spaces between [what I assume to be] the function parameters.
The function definition for lua_pushstring is
LUA_API const char *(lua_pushstring) (lua_State *L, const char *s);
SWIG_RUNTIME_VERSION is a #define equal to "4"
SWIG_TYPE_TABLE_NAME is defined in the following block:
#ifdef SWIG_TYPE_TABLE
# define SWIG_QUOTE_STRING(x) #x
# define SWIG_EXPAND_AND_QUOTE_STRING(x) SWIG_QUOTE_STRING(x)
# define SWIG_TYPE_TABLE_NAME SWIG_EXPAND_AND_QUOTE_STRING(SWIG_TYPE_TABLE)
#else
# define SWIG_TYPE_TABLE_NAME
#endif
Can anyone explain what is going on here?
For further reference, the code is used in the swig project on GitHub: luarun.swg:353 and luarun.swg:364.

Static string concatination. "Hello " "World" is the same as "Hello World".

The constant strings are cat'ed together
The following code produces output equal to all three strings in the parameter list.
#include <iostream>
void f(const char* s) {
std::cerr << s << std::endl;
}
int main() {
f("sksksk" "jksjksj" "sjksjks");
}

C++ (and C) will automatically concatenate adjacent string literals. So
std::cout << "Hello " "World" << std::endl;
will output "Hello World". This only applies to literals though, not to variables:
std::string a = "Hello ", b = "World";
std::string c = a b //error, use a + b
You can use std::string's operator+ for that purpose (or strcat, but avoid that if you can).
This feature is mainly useful when we have a really long string literal that doesn't fit on one line:
process_string("The quick brown fox jumps over "
"the lazy dog");
It can also be useful with preprocessing directives, as in your example.

Related

How to cleanly use: const char* and std::string?

tl:dr
How can I concatenate const char* with std::string, neatly and
elegantly, without multiple function calls. Ideally in one function
call and have the output be a const char*. Is this impossible, what
is an optimum solution?
Initial Problem
The biggest barrier I have experienced with C++ so far is how it handles strings. In my opinion, of all the widely used languages, it handles strings the most poorly. I've seen other questions similar to this that either have an answer saying "use std::string" or simply point out that one of the options is going to be best for your situation.
However this is useless advice when trying to use strings dynamically like how they are used in other languages. I cannot guaranty to always be able to use std::string and for the times when I have to use const char* I hit the obvious wall of "it's constant, you can't concatenate it".
Every solution to any string manipulation problem I've seen in C++ requires repetitive multiple lines of code that only work well for that format of string.
I want to be able to concatenate any set of characters with the + symbol or make use of a simple format() function just how I can in C# or Python. Why is there no easy option?
Current Situation
Standard Output
I'm writing a DLL and so far I've been output text to cout via the << operator. Everything has been going fine so far using simple char arrays in the form:
cout << "Hello world!"
Runtime Strings
Now it comes to the point where I want to construct a string at runtime and store it with a class, this class will hold a string that reports on some errors so that they can be picked up by other classes and maybe sent to cout later, the string will be set by the function SetReport(const char* report). So I really don't want to use more than one line for this so I go ahead and write something like:
SetReport("Failure in " + __FUNCTION__ + ": foobar was " + foobar + "\n"); // __FUNCTION__ gets the name of the current function, foobar is some variable
Immediately of course I get:
expression must have integral or unscoped enum type and...
'+': cannot add two pointers
Ugly Strings
Right. So I'm trying to add two or more const char*s together and this just isn't an option. So I find that the main suggestion here is to use std::string, sort of weird that typing "Hello world!" doesn't just give you one of those in the first place but let's give it a go:
SetReport(std::string("Failure in ") + std::string(__FUNCTION__) + std::string(": foobar was ") + std::to_string(foobar) + std::string("\n"));
Brilliant! It works! But look how ugly that is!! That's some of the ugliest code I've every seen. We can simplify to this:
SetReport(std::string("Failure in ") + __FUNCTION__ + ": foobar was " + std::to_string(foobar) + "\n");
Still possibly the worst way I've every encounter of getting to a simple one line string concatenation but everything should be fine now right?
Convert Back To Constant
Well no, if you're working on a DLL, something that I tend to do a lot because I like to unit test so I need my C++ code to be imported by the unit test library, you will find that when you try to set that report string to a member variable of a class as a std::string the compiler throws a warning saying:
warning C4251: class 'std::basic_string<_Elem,_Traits,_Alloc>' needs to have dll-interface to be used by clients of class'
The only real solution to this problem that I've found other than "ignore the warning"(bad practice!) is to use const char* for the member variable rather than std::string but this is not really a solution, because now you have to convert your ugly concatenated (but dynamic) string back to the const char array you need. But you can't just tag .c_str() on the end (even though why would you want to because this concatenation is becoming more ridiculous by the second?) you have to make sure that std::string doesn't clean up your newly constructed string and leave you with garbage. So you have to do this inside the function that receives the string:
const std::string constString = (input);
m_constChar = constString.c_str();
Which is insane. Because now I traipsed across several different types of string, made my code ugly, added more lines than should need and all just to stick some characters together. Why is this so hard?
Solution?
So what's the solution? I feel that I should be able to make a function that concatenates const char*s together but also handle other object types such as std::string, int or double, I feel strongly that this should be capable in one line, and yet I'm unable to find any examples of it being achieved. Should I be working with char* rather than the constant variant, even though I've read that you should never change the value of char* so how would this help?
Are there any experienced C++ programmers who have resolved this issue and are now comfortable with C++ strings, what is your solution? Is there no solution? Is it impossible?
The standard way to build a string, formatting non-string types as strings, is a string stream
#include <sstream>
std::ostringstream ss;
ss << "Failure in " << __FUNCTION__ << ": foobar was " << foobar << "\n";
SetReport(ss.str());
If you do this often, you could write a variadic template to do that:
template <typename... Ts> std::string str(Ts&&...);
SetReport(str("Failure in ", __FUNCTION__, ": foobar was ", foobar, '\n'));
The implementation is left as an exercise for the reader.
In this particular case, string literals (including __FUNCTION__) can be concatenated by simply writing one after the other; and, assuming foobar is a std::string, that can be concatenated with string literals using +:
SetReport("Failure in " __FUNCTION__ ": foobar was " + foobar + "\n");
If foobar is a numeric type, you could use std::to_string(foobar) to convert it.
Plain string literals (e.g. "abc" and __FUNCTION__) and char const* do not support concatenation. These are just plain C-style char const[] and char const*.
Solutions are to use some string formatting facilities or libraries, such as:
std::string and concatenation using +. May involve too many unnecessary allocations, unless operator+ employs expression templates.
std::snprintf. This one does not allocate buffers for you and not type safe, so people end up creating wrappers for it.
std::stringstream. Ubiquitous and standard but its syntax is at best awkward.
boost::format. Type safe but reportedly slow.
cppformat. Reportedly modern and fast.
One of the simplest solution is to use an C++ empty string. Here I declare empty string variable named _ and used it in front of string concatenation. Make sure you always put it in the front.
#include <cstdio>
#include <string>
using namespace std;
string _ = "";
int main() {
char s[] = "chararray";
string result =
_ + "function name = [" + __FUNCTION__ + "] "
"and s is [" + s + "]\n";
printf( "%s", result.c_str() );
return 0;
}
Output:
function name = [main] and s is [chararray]
Regarding __FUNCTION__, I found that in Visual C++ it is a macro while in GCC it is a variable, so SetReport("Failure in " __FUNCTION__ "; foobar was " + foobar + "\n"); will only work on Visual C++. See: https://msdn.microsoft.com/en-us/library/b0084kay.aspx and https://gcc.gnu.org/onlinedocs/gcc/Function-Names.html
The solution using empty string variable above should work on both Visual C++ and GCC.
My Solution
I've continued to experiment with different things and I've got a solution which combines tivn's answer that involves making an empty string to help concatenate long std::string and character arrays together and a function of my own which allows single line copying of that std::string to a const char* which is safe to use when the string object leaves scope.
I would have used Mike Seymour's variadic templates but they don't seem to be supported by the Visual Studio 2012 I'm running and I need this solution to be very general so I can't rely on them.
Here is my solution:
Strings.h
#ifndef _STRINGS_H_
#define _STRINGS_H_
#include <string>
// tivn's empty string in the header file
extern const std::string _;
// My own version of .c_str() which produces a copy of the contents of the string input
const char* ToCString(std::string input);
#endif
Strings.cpp
#include "Strings.h"
const std::string str = "";
const char* ToCString(std::string input)
{
char* result = new char[input.length()+1];
strcpy_s(result, input.length()+1, input.c_str());
return result;
}
Usage
m_someMemberConstChar = ToCString(_ + "Hello, world! " + someDynamicValue);
I think this is pretty neat and works in most cases. Thank you everyone for helping me with this.
As of C++20, fmtlib has made its way into the ISO standard but, even on older iterations, you can still download and use it.
It gives similar capabilities as Python's str.format()(a), and your "ugly strings" example then becomes a relatively simple:
#include <fmt/format.h>
// Later on, where code is allowed (inside a function for example) ...
SetReport(fmt::format("Failure in {}: foobar was {}\n", __FUNCTION__, foobar));
It's much like the printf() family but with extensibility and type safety built in.
(a) But, unfortunately, not its string interpolation feature (use of f-strings), which has the added advantage of putting the expressions in the string at the place where they're output, something like:
set_report(f"Failure in {__FUNCTION__}: foobar was {foobar}\n");
If fmtlib ever got that capability, I'd probably wet my pants in excitement :-)

Macro string concatenation

I use macros to concatenate strings, such as:
#define STR1 "first"
#define STR2 "second"
#define STRCAT(A, B) A B
which having STRCAT(STR1 , STR2 ) produces "firstsecond".
Somewhere else I have strings associated to enums in this way:
enum class MyEnum
{
Value1,
Value2
}
const char* MyEnumString[] =
{
"Value1String",
"Value2String"
}
Now the following does not work:
STRCAT(STR1, MyEnumString[(int)MyEnum::Value1])
I was just wondering whether it possible to build a macro that concatenate a #defined string literal with a const char*? Otherwise, I guess I'll do without macro, e.g. in this way (but maybe you have a better way):
std::string s = std::string(STR1) + MyEnumString[(int)MyEnum::Value1];
The macro works only on string literals, i.e. sequence of characters enclosed in double quotes. The reason the macro works is that C++ standard treats adjacent string literals like a single string literal. In other words, there is no difference to the compiler if you write
"Quick" "Brown" "Fox"
or
"QuickBrownFox"
The concatenation is performed at compile time, before your program starts running.
Concatenation of const char* variables needs to happen at runtime, because character pointers (or any other pointers, for that matter) do not exist until the runtime. That is why you cannot do it with your CONCAT macro. You can use std::string for concatenation, though - it is one of the easiest solutions to this problem.
It's only working for char literals that they can be concatenated in this way:
"A" "B"
This will not work for a pointer expression which you have in your sample, which expands to a statement like
"STR1" MyEnumString[(int)MyEnum::Value1];
As for your edit:
Yes I would definitely go for your proposal
std::string s = std::string(STR1) + MyEnumString[(int)MyEnum::Value1];
Your macro is pretty unnecessary, as it can only work with string literals of the same type. Functionally it does nothing at all.
std::string s = STRCAT("a", "b");
Is exactly the same as:
std::string s = "a" "b";
So I feel that it's best to just not use the macro at all. If you want a runtime string concatenating function, a more C++-canonical version is:
inline std::string string_concat(const std::string& a, const std::string& b)
{
return a + b;
}
But again, it seems almost pointless to have this function when you can just do:
std::string a = "a string";
std::string ab = a + "b string";
I can see limited use for a function like string_concat. Maybe you want to work on arbitrary string types or automatic conversion between UTF-8 and UTF-16...

Can a compilation error be forced if a string argument is not a string literal?

Let's say I have these two overloads:
void Log(const wchar_t* message)
{
// Do something
}
void Log(const std::wstring& message)
{
// Do something
}
Can I then in the first function add some compile-time verifiction that the passed argument is a string literal?
EDIT: A clarification on why this would be good in my case; my current high-frequency logging uses only string literals and can hence be optimized a lot when there are non-heap allocation guarantees. The second overload doesn't exist today, but I might want to add it, but then I want to keep the first one for extreme scenarios. :)
So this grew out of Keith Thompson's answer... As far as I know, you can't restrict string literals to only normal functions, but you can do it to macro functions (through a trick).
#include <iostream>
#define LOG(arg) Log(L"" arg)
void Log(const wchar_t *message) {
std::wcout << "Log: " << message << "\n";
}
int main() {
const wchar_t *s = L"Not this message";
LOG(L"hello world"); // works
LOG(s); // terrible looking compiler error
}
Basically, a compiler will convert "abc" "def" to look exactly like "abcdef". And likewise, it will convert "" "abc" to "abc". You can use this to your benefit in this case.
I also saw this comment on the C++ Lounge, and that gave me another idea of how to do this, which gives a cleaner error message:
#define LOG(arg) do { static_assert(true, arg); Log(arg); } while (false)
Here, we use the fact that static_assert requires a string literal as it's second argument. The error that we get if we pass a variable instead is quite nice as well:
foo.cc:12:9: error: expected string literal
LOG(s);
^
foo.cc:3:43: note: expanded from macro 'LOG'
#define LOG(arg) do { static_assert(true, arg); Log(arg); } while (false)
I believe the answer to your question is no -- but here's a way to do something similar.
Define a macro, and use the # "stringification" operator to guarantee that only a string literal will be passed to the function (unless somebody bypasses the macro and calls the function directly). For example:
#include <iostream>
#define LOG(arg) Log(#arg)
void Log(const char *message) {
std::cout << "Log: " << message << "\n";
}
int main() {
const char *s = "Not this message";
LOG("hello world");
LOG(hello world);
LOG(s);
}
The output is:
Log: "hello world"
Log: hello world
Log: s
The attempt to pass s to LOG() did not trigger a compile-time diagnostic, but it didn't pass that pointer to the Log function.
There are at least two disadvantages to this approach.
One is that it's easily bypassed; you may be able to avoid that by searching the source code for references to the actual function name.
The other is that stringifying a string literal doesn't just give you the same string literal; the stringified version of "hello, world" is "\"hello, world\"". I suppose your Log function could strip out any " characters in the passed string. You may also want to handle backslash escapes; for example, "\n" (a 1-character string containing a newline) is stringified as "\\n" (a 2-character string containing a backslash and the letter n).
But I think a better approach is not to rely on the compiler to diagnose calls with arguments other than string literals. Just use some other tool to scan the source code for calls to your Log function and report any calls where the first argument isn't a string literal. If you can enforce a particular layout for the calls (for example, the tokens Log, (, and a string literal on the same line), that shouldn't be too difficult.
You can't detect string literals directly but you can detect if the argument is an array of characters which is pretty close. However, you can't do it from the inside, you need to do it from the outside:
template <std::size_t Size>
void Log(wchar_t const (&message)[Size]) {
// the message is probably a string literal
Log(static_cast<wchar_t const*>(message);
}
The above function will take care of wide string literals and arrays of wide characters:
Log(L"literal as demanded");
wchar_t non_literal[] = { "this is not a literal" };
Log(non_literal); // will still call the array version
Note that the information about the string being a literal isn't as useful as one might hope for. I frequently think that the information could be used to avoid computing the string length but, unfortunately, string literals can still embed null characters which messes up static deduction of the string length.
If you define Log as a macro instead, and call separate methods for literal versus std::wstring handling, some variation of the following should work:
#define Log(x) ((0[#x] == 'L' && 1[#x] == '"') ? LogLiteral(x) : LogString(x))
void
LogLiteral (const wchar_t *s) {
//...do something
}
void
LogString (const std::wstring& s) {
//...do something
}
The trick is that you need opposing definitions of LogLiteral() so that the compilation will pass, but it should never be called.
inline void LogLiteral (const std::wstring &s) {
throw std::invalid_argument(__func__);
}
This code gives you the behavior of an overloaded Log() method, in that you can pass either a string literal or a non-string literal to the Log() macro, and it will end up calling either LogLiteral() or LogString(). This gives compile time verification in that the compiler will not pass anything except what the code recognizes as a string literal to the call to LogLiteral(). At sufficient optimizations, the conditional branch can be removed, since every instance of the check is static (on GCC, it is removed).
Here's a quick example I just whipped up using the printf hack I suggested in the comments above:
#include <cstdio>
#define LOG_MACRO(x) do { if (0) printf(x); Log(x); } while (0)
void Log(const char *message)
{
// do something
}
void function(void)
{
const char *s = "foo";
LOG_MACRO(s);
LOG_MACRO("bar");
}
Output from compiling this one with Clang appears to be exactly what you're looking for:
$ clang++ -c -o example.o example.cpp
example.cpp:13:15: warning: format string is not a string literal
(potentially insecure) [-Wformat-security]
LOG_MACRO(s);
^
example.cpp:3:41: note: expanded from macro 'LOG_MACRO'
#define LOG_MACRO(x) do { if (0) printf(x); Log(x); } while (0)
^
1 warning generated.
I did have to switch to printf rather than wprintf, since the latter appears not to generate the warning - I guess that's probably a Clang bug, though.
GCC's output is similar:
$ g++ -c -o example.o example.cpp
example.cpp: In function ‘void function()’:
example.cpp:13: warning: format not a string literal and no format arguments
example.cpp:13: warning: format not a string literal and no format arguments
Edit: You can see the Clang bug here. I just added a comment about -Wformat-security.
I don't think you can enforce to pass only a string literal to a function, but literals are character arrays, what you can enforce:
#include <iostream>
template<typename T>
void log(T) = delete; //Disable everything
template <std::size_t Size>
void log(const wchar_t (&message)[Size]) //... but const wchar_t arrays
{
std::cout << "yay" << std::endl;
}
const wchar_t * get_str() { return L"meow"; }
int main() {
log(L"foo"); //OK
wchar_t arr[] = { 'b', 'a', 'r', '0' };
log(arr); //Meh..
// log(get_str()); //compile error
}
Downside is that if you have a runtime character array, it will work as well, but won't work for the usual runtime c-style strings.
But, if you can work with a slightly different syntax, then the answer is YES:
#include <cstddef>
#include <iostream>
void operator"" _log ( const wchar_t* str, size_t size ) {
std::cout << "yay" << std::endl;
}
int main() {
L"Message"_log;
}
Of course, both solution needs a C++11-compatible compiler (example tested with G++ 4.7.3).
Adding this alternative for future reference. It comes from the SO question Is it possible to overload a function that can tell a fixed array from a pointer?
#include <iostream>
#include <type_traits>
template<typename T>
std::enable_if_t<std::is_pointer<T>::value>
foo(T)
{
std::cout << "pointer\n";
}
template<typename T, unsigned sz>
void foo(T(&)[sz])
{
std::cout << "array\n";
}
int main()
{
char const* c = nullptr;
char d[] = "qwerty";
foo(c);
foo(d);
foo("hello");
}
The above snippet compiles and runs fine on http://webcompiler.cloudapp.net/

C++ how to add more strings into a method

I have been working in Java since I started programming and decided to learn c++.
What I wrote in Java looked like this:
showMessage("Hello world" + randomNumber);
And it showed text + integer or float or whatever. But it wont work in c++.
Error message by xCode: Invalid operands to binary expression ('const char *' and 'float')
Cheers!
You can do a sprintf according to Anton, or to be more c++:
std::stringstream ss;
ss << "Hello, world " << randomNumber;
showmessage(ss.str());
(there's nothing wrong with sprintf, especially if you use snprintf instead).
ostringstream os;
os<<"HelloWorld"<<randomnumber;
string s;
s = os.str();
string s now contains the string you want as a string object.
Also you can use boost::lexical_cast to cast numbers into strings which is fastest method in most cases:
showMessage("Hello world" + boost::lexical_cast<std::string>(randomNumber));
showMessage declaration is
void showMessage(cosnt std::string& message)
Consider adding a new function that is able to convert several types to std::string:
template<typename ty>
string to_str(ty t)
{
stringstream ss; ss << t;
return ss.str();
}
Usage:
"Hello World " + to_str(123)
Define a class S. Then write
showMessage( S() << "Hello world" << randomNumber );
I've coded up the S class too many times for SO, and it's a good exercise to create it, hence, not providing the source code.
Note that you can reasonably call it StringWriter or something like that, and then just use a typedef for more concise code in function calls.
I am not sure if c-style answer is fine, but I have already answer it here in a cocos2d-x question.
Trying to set up a CCLabelTTF with an integer as part of it's string in Cocos2d-X C++
With C++11:
showMessage("Hello world" + std::to_string(randomNumber));
you should print into the char* instead.
You could do something like
char* tempBuffer = new char[256];
sprintf_s(tempBuffer, 256, "Hello world %d", randomNumber);
showMessage(tempBuffer);
In C++ the standard way to concatenate strings and primitives is to use stringstream. Which fulfils the same functionality (and a little bit more) as StringBuilder in Java (of course its API differs). However, if you are comfortable using cout then you should be fine.
eg.
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
int main () {
stringstream ss;
ss << "Some string - " << 124; // build string
string str = ss.str(); // extract string
cout << str << endl;
return 0;
}
Quick reference for stringstream http://www.cplusplus.com/reference/iostream/stringstream/stringstream/

C++ Macro riddle: Printing the name of the TYPE

In a macro I can use xxxx_##TYPE and ##TYPE##_xxxxx to have the TYPE name filled in correctly, but I can't use ##TYPE## in the middle of a string e.g. (print "##TYPE## is the name of the type";)
Is there a way around it?
You can do this by combining two features. One is ''stringification'', whereby a macro argument is converted to a string by prefixing it with #. (This is related to, but different from, the ''token-pasting'' operator ## that you're obviously already familiar with.) The other is the fact that C++, when given multiple string literals in a row, will combine them into a single string. For example, "a" "b" "c" is equivalent to "abc". I'm not clear on exactly how your macro is to be defined, so I can't show you exactly what to type, but a full explanation and some good working examples are at http://gcc.gnu.org/onlinedocs/cpp/Stringification.html.
Edited to add a simple example, at Kleist's request. This program:
#include <stdio.h>
#define PRINT_WHAT_THE_NAME_OF_THE_TYPE_IS(TYPE) \
printf("%s\n", "'" #TYPE "' is the name of the type.")
int main()
{
PRINT_WHAT_THE_NAME_OF_THE_TYPE_IS(Mr. John Q. Type);
return 0;
}
will print this:
'Mr. John Q. Type' is the name of the type.
(This will run in either C or C++. The reason I wrote it C-ishly is that in my experience these sorts of preprocessor tricks are more common in C code than in real C++ code; but if you wanted to use std::cout << instead of printf, you absolutely could.)
## is the token pasting operator and it takes two different tokens and pastes them together to make a single token. The entire string literal is considered a single token, thus the pasting operator doesn't work within it. See http://gcc.gnu.org/onlinedocs/gcc-4.0.4/cpp/Tokenization.html
String literals will be concatenated when they are next to each other.
#define QUOTE(X) #X
#define DOSTUFF(TYPE) \
void print_ ## TYPE () { \
static const char *str = QUOTE(TYPE) " is the name of the type\n"; \
printf(str); \
}
DOSTUFF(Foo);
int main(int argc, char ** argv) {
print_Foo();
return 0;
}
Output of g++ -E -c main.cpp will show you what this gets preprocessed into.
# 16 "main.cpp"
void print_Foo () {
static const char *str = "Foo" " is the name of the type\n";
printf(str);
};
int main(int argc, char ** argv) {
print_Foo();
return 0;
}