return static character array by using reference - c++

Now I want to write a new version of the following code:
const char * f() {
return "Hello";
}
const char *pf = f();
I wonder how to use reference instead of pointer.
I have one idea by using string.
Is there a more straight way to solve this?
UPDATE:
I read the answer and comments carefully. I got another idea is to treat the return value as a const char array. But this solution seems too complicated and not so clear as a pointer.

If you want to know the syntax then the definition will look the following way
#include <iostream>
const char ( & ( f() ) )[6] { return ( "Hello" ); }
int main()
{
std::cout << f() << std::endl;
}
Or as #Jarod42 advices you can use a typedef that the fiunction definition woild look simpler
#include <iostream>
const char ( & ( f() ) )[6] { return ( "Hello" ); }
typedef const char ( &Array_Ref )[6];
Array_Ref g() { return ( "Hello" ); }
int main()
{
std::cout << f() << std::endl;
std::cout << g() << std::endl;
Array_Ref s = g();
std::cout << s << std::endl;
}
If you want to use std::string then it would be better to write the function as
std::string f() { return ( "Hello" ); }

Related

C++ function map with varialbles input

In C++, I want to use a map of functions with different type of input or output.
Do to so, I found that using a map with any type could be a way.
But I get several problems. First, I can not use directly the functions in the map.
However, I can use a lambda function to wrap the functions then use these lambda functions in the map.
But, I get a second problem, I still need to cast with the lambda function which is not a variable. This makes a use from a string variable complicated.
Here is a MWE:
#include <any>
#include <functional>
#include <iostream>
#include <map>
#include <string>
void funct0()
{
std::cout << "funct0" << std::endl;
}
void funct1(int p)
{
std::cout << "funct1 " << p << std::endl;
};
int funct2(int p, std::string s)
{
std::cout << "funct2 " << s << std::endl;
return p+1;
};
float funct3(int a, float b)
{
std::cout << "funct3 " << std::endl;
return a +b;
}
auto funct4(int a, float b)
{
std::cout << "funct4 " << std::endl;
std::vector<float> v;
v.push_back(a);
v.push_back(b);
return v;
}
int main()
{
std::map<std::string, std::any> mapFunct;
mapFunct["F0"]= funct0;
// mapFunct["FO"](); // error: no match for call to ‘(std::map<std::__cxx11::basic_string<char>, std::any>::mapped_type {aka std::any}) ()’
mapFunct["F1"]= funct1;
// mapFunct["F1"](12); // error: no match for call to ‘(std::map<std::__cxx11::basic_string<char>, std::any>::mapped_type {aka std::any}) (int)’
// WHY THIS IS NOT WORKING ?
// From this link: https://stackoverflow.com/questions/61969316/is-it-possible-to-put-lambda-expressions-into-a-map-or-list-in-c
auto lambda0 = [](){funct0();};
auto lambda1 = [](int p) { funct1(p); return p; };
auto lambda2 = [](int p, std::string s) { return funct2(p,s); };
auto lambda3 = [](int a, float b){return funct3(a,b);};
auto lambda4 = [](int a, float b){return funct4(a,b);};
std::map<std::string, std::any> mapLambda;
mapLambda["L0"]=lambda0;
mapLambda["L1"]=lambda1;
mapLambda["L2"]=lambda2;
mapLambda["L3"]=lambda3;
mapLambda["L4"]=lambda4;
std::any_cast<decltype(lambda0)>(mapLambda["L0"])();
std::any_cast<decltype(lambda1)>(mapLambda["L1"])(2);
std::cout << std::any_cast<decltype(lambda2)>(mapLambda["L2"])(4, "HELLO") << std::endl;
std::cout << std::any_cast<decltype(lambda3)>(mapLambda["L3"])(3, 4.32) << std::endl ;
auto vec4= std::any_cast<decltype(lambda4)>(mapLambda["L4"])(6, 9.1);
std::cout << "vec4" << vec4[1] << vec4[2] << std::endl ;
std::vector<std::string> inputString;
inputString.push_back("L3(3, 4.32)");
inputString.push_back("L4(6, 9.1)");
// Using a for loop with iterator
for(auto it = std::begin(inputString); it != std::end(inputString); ++it) {
std::cout << *it << "\n";
std::string line=*it;
std::string functionInput = line.substr( 0, line.find("(") );
std::cout << functionInput << std::endl;
// argumentsInput= ;
mapLambda[functionInput](argumentsInput);
}
};
So my question are:
Why my example is working with lambda functions and not the functions ?
How can I make the last part of my example works only from the inputString variable? (ie, knowing the correct casting from the string variable)
What you probably want is something like this:
using CallWrapper = std::function<void(const std::string&)>;
std::map<std::string, CallWrapper> mapLambda;
mapLambda["L0"] = [funct0](const std::string&) { funct0(); };
mapLambda["L1"] = [funct1](const std::string& args) {
int p = ...; // parse the argument from `args`
funct1(p);
};
mapLambda["L2"] = [funct2](const std::string& args) {
// parse the arguments from `args`
int p = ...;
std::string s = ...;
funct2(p, s);
};
Now you can run the loop you envision:
for(const std::string& line : inputString) {
size_t pos = line.find('(');
std::string functionInput = line.substr( 0, pos);
std::string argumentsInput = line.substr(pos);
mapLambda[functionInput](argumentsInput);
}
The hard part, of course, is "parse the arguments from args", left as an exercise for the reader.
std::any_cast needs to cast to constructible types. A standard C++ function is neither a type nor constructible (it's just a group of statements given a name [edit: this isn't technically true, but what's going on under the hood is fairly complicated]), but std::function is. One way to get around this is to assign a standard C++ function to an std::function. Here's an example using a std::map like you were using:
#include <any>
#include <functional>
#include <iostream>
#include <map>
int my_func(int val) { return val + 1; }
std::function<int(int)> f = my_func;
int main() {
auto my_map = std::map<std::string, std::any>();
my_map["func"] = f;
std::cout << std::any_cast<std::function<int(int)>>(my_map["func"])(13) << std::endl; // prints "14"
return 0;
}
Lambdas are constructible types, which is why your code works for lambdas.
To answer your second question: I don't think it's possible. Functions with different signatures are different types, and you have to know what you're casting to. std::function<int(int, string)> and std::function<float(int, float)>, for example, are different types.
Also, the intended purpose of lambdas is to be used once then discarded. If you're going to keep lambdas around for reuse, it's better to simply just use functions.

How to convert a long long in const char* in c++

I tried to use a function that converts a long long to an const char* because the function socket->write in my code needs a parameter with the datatype const char *data. But if I look to my output, convertedLabel is nothing and I don't know why. I think I haven't the right converting function.
My code:
void ServerNet::sendData(long long label270) {
std::cout << "First:" << std::endl;
std::cout << label270 << std::endl;
//Error is here:
const char* convertedLabel = reinterpret_cast<char * const>(label270);
std::cout << "Then:" << std::endl;
std::cout << convertedLabel << std::endl;
socket->write(convertedLabel);
}
Output:
First:
2173457687
Then:
#include <iostream>
#include <string>
void SendData(const char* Data) {
std::cout << Data << std::endl;
}
int main() {
long long label270 = 2173457687;
SendData(std::to_string(label270).c_str());
return 0;
}
With yours guys tipps I handled the problem. Here's the solution:
void ServerNet::sendData(long long label270) {
std::string convertedLabel = std::to_string(label270);
const char *test = convertedLabel.c_str();
socket->write(test);
}
Thanks everybody!

Can i make a function return more than one type? [duplicate]

This question already has answers here:
Can a C++ function return more than one value? [duplicate]
(11 answers)
Closed 8 years ago.
how to make a function return multiple types ?
i want to make a function called view that return view Name, ID and salary
can i make a single one (get) function to do so ?
You can return a struct or a std::tuple.
Something like:
struct foo
{
std::string Name;
unsingned int ID;
unsigned int salary;
};
foo bar()
{
return {"Smith", 42, 1000};
}
You can use standard class std::tuple. For example
#include <iostream>
#include <string>
#include <tuple>
std::tuple<std::string, int, float> f()
{
return std::make_tuple( "Doxim", 1, 3500.00 );
}
int main()
{
auto t = f();
std::cout << std::get<0>( t ) << '\t'
<< std::get<1>( t ) << '\t'
<< std::get<2>( t ) << std::endl;
return 0;
}
The output is
Doxim 1 3500
Or
#include <iostream>
#include <string>
#include <tuple>
std::tuple<std::string, int, float> f()
{
return std::make_tuple( "Doxim", 1, 3500.00 );
}
enum { NAME, ID, SALARY };
int main()
{
auto t = f();
std::cout << std::get<NAME>( t ) << '\t'
<< std::get<ID>( t ) << '\t'
<< std::get<SALARY>( t ) << std::endl;
return 0;
}
You can make a function return a structure containing those attributes.
struct Foo
{
int value1;
int value2;
};
Foo SomeFunction()
{
Foo f = { 1, 2 };
return f;
}
You have two options :
Either use in-out parameters or create a structure/class containing all the types you need.

Odd behavior with ostringstream

I was trying to think of a clever way to concatenate various things into a single string argument for a function without having to use an ostringstream explicitly. I thought of:
#define OSS(...) \
dynamic_cast<std::ostringstream const&>(std::ostringstream() << __VA_ARGS__).str()
However, given:
void f( string const &s ) {
cout << s << endl;
}
int main() {
char const *const s = "hello";
f( OSS( '{' << s << '}' ) );
ostringstream oss;
oss << '{' << s << '}';
cout << oss.str() << endl;
}
it prints when run:
123hello}
{hello}
where 123 is the ASCII code for }. Why does using the macro get it wrong?
FYI: I'm currently using g++ 4.2.1 on Mac OS X as part of Xcode 3.x.
Solution I'm now using
class string_builder {
public:
template<typename T>
string_builder& operator,( T const &t ) {
oss_ << t;
return *this;
}
operator std::string() const {
return oss_.str();
}
private:
std::ostringstream oss_;
};
#define BUILD_STRING(...) (string_builder(), __VA_ARGS__)
using namespace std;
void f( string const &s ) {
cout << s << endl;
}
int main() {
char const *const s = "hello";
f( BUILD_STRING( '{', s, '}' ) );
}
std::ostringstream() is temporary which thus can be bound only to const references. Standalone operator<< (which take non const references as first argument) aren't considered and only the member one are. The best match in these for a char is converting the char to int.
This problems occurs often with string literals whose address is then displayed.
To solve the problem, the trick is to find a way to transform the temporary in a reference. The member operator<<s do that, but only the one for manipulator does it without side effect and only if the manipulator is a noop -- flush could be used. The members flush and write are also candidates. So for instance
#define OSS(...) \
dynamic_cast<std::ostringstream const&>(std::ostringstream().flush() << __VA_ARGS__).str()
A better thread-safe solution without involving the cumbersome macro.
The original call to function is this:
f( OSS( '{' << s << '}' ) );
How about if the call is just this:
f(stringbuilder() << '{' << s << '}' );
where stringbuilder is implemented as:
struct stringbuilder
{
std::ostringstream ss;
template<typename T>
stringbuilder & operator << (const T &data)
{
ss << data;
return *this;
}
operator string() { return ss.str(); }
};
void f( string const &s ) {
cout << s << endl;
}
Test:
int main() {
char const *const s = "hello";
f(stringbuilder() << '{' << s << '}' );
}
Output:
{hello}
Online Demo : http://ideone.com/QHFf4

Question on reuse of pointers after passing to functions

So, when I pass a const char * to a function once, can I use it again? It appears to end up spitting out crap to me.
const char *config_file = "file.txt";
function(int x, config_file);
cout << "Number" << x;
secondfunction(int y, config_file);
Do I need to make another pointer to config_file?
If so, how do I do that?
Thanks!
No, your can use it just fine. Despite the fact that the code you gave is uncompilable, I think I understand what you're asking.
A code segment like:
const char *x = "Hello";
fnA (x);
fnB (x);
should be just fine.
If you find that fnB is not getting what it expects then either:
fnA is changing what x points to (normally not possible since it's a const char *); or
some unshown piece of code is changing the pointer itself; or
something is corrupting the memory.
Try this code as an example:
#include <iostream>
#include <iomanip>
static void fnA (const char *a) {
std::cout << "fnA: [" << a << "]" << std::endl;
}
static void fnB (const char *b) {
std::cout << "fnB: [" << b << "]" << std::endl;
}
int main (void) {
const char *x = "Hello";
fnA (x);
fnB (x);
return 0;
}
It outputs, as expected:
fnA: [Hello]
fnB: [Hello]