c++ Externally visible const - c++

I have a function which returns zero on success, or the line number where an error was detected:
int func() {
// stuff
if (something is wrong) {
return __LINE__;
}
// more stuff
if (something else is wrong) {
return __LINE__;
}
// all good
return 0;
}
Real callers only check whether the return value is zero or not, often like this:
int ret = func();
if (ret != 0) {
return ret;
}
However, during tests I would like to check the actual return value, to verify that a certain fail condition was triggered:
int ret = func();
EXPECT_EQ(42, ret);
This poses a problem, because when the source file of func() is edited, the lines of the return statements, and hence the values returned, also change. I would like the line number values to be available to the callers of func().
It is possible to "export" line numbers like this:
// header
extern const int line_number;
// source
const int line_number = __LINE__;
Unfortunately, this only works for line numbers outside a function. I would like something like this:
if (something is wrong) {
const int line_number = __LINE__; return __LINE__;
// or some other const thing
}
that can be read from another translation unit (file).
I tried static const int line = __LINE__, but that has two flaws:
it's not the definition of line_number declared in the header.
it may not be set until execution passes over it.

Here an example how I would solve this easily:
struct FuncErrorCodes {
enum Type {
OK = 0,
SOMETHING_IS_WRONG,
SOMETHING_ELSE_IS_WRONG,
...
};
};
typedef FuncErrorCodes::Type FuncErrorCode;
FuncErrorCode func() {
// stuff
if (something is wrong) {
return FuncErrorCodes::SOMETHING_IS_WRONG;
}
// more stuff
if (something else is wrong) {
return FuncErrorCodes::SOMETHING_ELSE_IS_WRONG;
}
...
// all good
return FuncErrorCodes::OK;
}
I don't see any reason why I would want to use __LINE__ for error codes.
In the usual case the return code can still be tested against 0 (or better yet FuncErrorCodes::OK) and I'd have no problem testing for the particular error reasons, like for example:
FuncErrorCode rc = func();
EXPECT_EQ(FuncErrorCodes::SOMETHING_IS_WRONG, ret);
EDIT: Note that even if you managed to export the "last line set to the error code" it would not help you in any way, because that would be the exact value the function is returning (so you already know it). For it to actually work, you would need separate variable for each possible error line, which will then contain the particular line number (so that it can be checked against the function return code to see if the particular error happened).
I.e. you would need something like:
extern int something_wrong_line_number;
extern int something_else_wrong_line_number;
if (something is wrong) {
something_wrong_line_number = __LINE__; return __LINE__;
}
if (something else is wrong) {
something_else_wrong_line_number = __LINE__; return __LINE__;
}
// etc. - but it will of course still not work entirely well because the __LINE__ is only assigned if the error actually happens
And that is then no different to providing just the simple error codes for each particular error situation as I suggest (and it is much more complicated).

Related

tricky situations with cppcheck

I am facing a situation where i need cppchecks to pass but it gets tricky sometimes. What do you generally do in such circumstances ?
For example.
#include<iostream>
using namespace std;
void fun1();
int fun2();
int main()
{
fun1();
}
void fun1()
{
int retVal;
if (-1 == (retVal = fun2()))
{
cout <<"Failure. fun2 returned a -1"<< endl;
}
}
int fun2()
{
return -1;
}
We usually see code such as the above. cppcheck for the above file would give an output as below -
cppcheck --suppress=redundantAssignment
--enable='warning,style,performance,portability' --inline-suppr --language='c++' retval_neverused.cpp Checking retval_neverused.cpp... [retval_neverused.cpp:13]: (style) Variable 'retVal' is assigned a
value that is never used.
I don't want to add some dummy line printing retVal just for the sake of cppcheck. Infact it can be a situation where I throw an exception and I don't want the exception to have something trivial as the value of retVal in it.
CppCheck is kinda right though. You don't need retVal at all. just check the return value of fun2 directly: if( -1 == fun2() )
As an aside, assigning variables inside conditional expressions is really bad practice. It makes it a lot harder to catch typos where you meant to type == but actually typed =.
You could rewrite as:
const int retval = fun2();
if (retval == -1)
This technique is, IMHO, easier to debug because you can see, with a debugger, the value returned from fun2 before the if statement is executed.
Debugging with the function call in the if expression is a little more complicated to see the return value from the function.
One common way is with something like this:
#define OK_UNUSED(x) (void)x
void fun1()
{
int retVal;
if (-1 == (retVal = fun2()))
{
OK_UNUSED (retVal);
cout <<"Failure. fun2 returned a -1"<< endl;
}
}
This indicates to humans that retVal is intentionally unused and makes CppCheck think it's used, suppressing the warning.
Note that this macro should not be used if evaluating its parameter has consequences. In that case, you need something fancier like:
#define OK_UNUSED(x) if(false && (x)) ; else (void) 0

Elegant way for "if(T t = ...) { } else return t;"?

Is there a better way for this "idiom"?
if(State s = loadSomething()) { } else return s;
In other words, I want to do something, which may return an error (with a message) or a success state, and if there was an error I want to return it. This can become very repetitive, so I want to shorten it. For example
if(State s = loadFoobar(&loadPointer, &results)) { } else return s;
if(State s = loadBaz(&loadPointer, &results)) { } else return s;
if(State s = loadBuz(&loadPointer, &results)) { } else return s;
This must not use exceptions which I would favor otherwise (unsuitable for this build). I could write up a little class BooleanNegator<State> that stores the value, and negates its boolean evaluation. But I want to avoid doing this ad-hoc, and prefer a boost/standard solution.
You could do:
for (State s = loadSomething(); !s; ) return s;
but I am not sure if it is more elegant, and it is definitely less readable...
I assume the context is something like
State SomeFunction()
{
if(State s = loadSomething()) { } else return s;
return do_something_else();
}
without throwing exceptions where do_something_else() does something of relevance to SomeFunction() and returns a State. Either way, the result of continuing within the function needs to result in a State being returned, as falling off the end will cause the caller to exhibit undefined behaviour.
In that case, I would simply restructure the function to
State SomeFunction()
{
if (State s = loadSomething())
return do_something_else();
else
return s;
}
Implicit assumptions are that State has some operator (e.g. operator bool()) that can be tested, that copying a State is possible (implied by the existence of a loadSomething() that returns one) and relatively inexpensive, and that two instances of State can exist at one time.
Aside from some smart/hacky uses of different keywords to get the same behavior, or adding more-or-less complex extra templates or macros to get unless() keyword or to somehow manage to inject ! operator, I'd stick to just the basic things.
This is one of the places I'd (probably) inject extra "unnecessary" brackets:
void someFunction()
{
// some other code
{ State s = loadSomething(); if(!s) return s; }
// some other code
}
However, in this exact case, I'd expand it to emphasise the return keyword, which can be easily overlooked when it's squashed to a one-liner. So, unless the one-liner is repeated many times and unless it's clear&obvious that there's a return inside, I'd probably write:
void someFunction()
{
// some other code
{
State s = loadSomething();
if(!s)
return s;
}
// some other code
}
It might look like elevating the scope of the s, but actually it is equivalent to declaring State s in if(). All thanks to the extra brackets which explicitly limit the visibility of local s.
However, some people just "hate" seeing { .. } not coupled with a keyword/class/function/etc, or even consider it to be unreadable due to "suggesting that a if/while/etc keyword was accidentally deleted".
One more idea came to me after you added the repetitive example. You could have tried a trick known from scripting languages where && and || may return a non-bool values:
State s = loadFoobar(&loadPointer, &results);
s = s || loadBaz(&loadPointer, &results);
s = s || loadBuz(&loadPointer, &results);
if(!s) return s;
however there's a problem: in contrast to script languages, in C++ such overloads of && and || lose their short-circuit semantics which makes this attempt pointless.
However, as dyp pointed out the obvious thing, once the s scope is elevated, now simple if can be introduced back. Its visibility can be limited back again with extra {}:
{
State s;
if(!(s = loadFoobar(&loadPointer, &results))) return s;
if(!(s = loadBaz(&loadPointer, &results))) return s;
if(!(s = loadBuz(&loadPointer, &results))) return s;
}

Translate error codes to string to display

Is there a common way in C++ to translate an error code to a string to display it?
I saw somewhere a err2msg function, with a big switch, but is that really the best way?
Since C++ does not allow automatic 'translation' from enum values to enum names or similar, you need a function to do this. Since your error codes are not somehow defined in your O/S you need to translate it by yourself.
One approach is a big switch statement. Another is a table search or table lookup. What's best depends on error code set.
table search can be defined in this way:
struct {
int value;
const char* name;
} error_codes[] = {
{ ERR_OK, "ERR_OK" },
{ ERR_RT_OUT_OF_MEMORY, "ERR_RT_OUT_OF_MEMORY" },
{ 0, 0 }
};
const char* err2msg(int code)
{
for (int i = 0; error_codes[i].name; ++i)
if (error_codes[i].value == code)
return error_codes[i].name;
return "unknown";
}
In windows you can use FormatMessage(...) function either with error code return by GetLastError() function or directly to the suspected area.
Please see below links for examples.
http://msdn.microsoft.com/en-us/library/ms679351(v=VS.85).aspx
http://msdn.microsoft.com/en-us/library/ms680582(v=VS.85).aspx
I hope this will help you.
Similar to harper's idea, but a bit more generalized:
typedef std::map<int, const char*> error_code_tbl_t;
typedef error_code_tbl_t::value_type error_code_entry_t;
const error_code_entry_t error_code_tbl_[] = {
{ ERR_OK , "ERR_OK" },
{ ERR_RT_OUT_OF_MEMORY, "ERR_RT_OUT_OF_MEMORY" },
// ...
};
const error_code_tbl_t error_code_tbl( begin(error_code_tbl_)
, end (error_code_tbl_) );
const char* err2msg(int code)
{
const error_code_tbl_t::const_iterator it = error_code_tbl.find(code);
if(it == error_code_tbl.end())
return "unknown";
return it->second;
}
(Those begin() and end() functions can be found here.)
As far as I am concerned, error codes are just a subset of enums. Since we are not blessed in C++ with pretty enums (which makes logs somehow quite hard to parse), error codes are no more easier.
The solution is pretty simple for error codes though:
class ErrorCode
{
public:
ErrorCode(): message(0) {}
explicit ErrorCode(char const* m): message(m) {}
char const* c_str() const { return message; }
std::string toString() const
{
return message ? std::string(message) : std::string();
}
private:
char const* message;
};
std::ostream& operator<<(std::ostream& out, ErrorCode const& ec)
{
return out << ec.c_str();
}
Of course you can supply the traditional ==, !=, <, etc...
It's simple!
It's fast (the code IS the string, no look-up involved)
It's type safe (you cannot accidentally mix it up with another type)
The idea is to return pointers to the text instead of error codes (though wrapped in a class for type safety).
Usage:
// someErrors.h
extern ErrorCode const ErrorOutOfMemory;
// someErrors.cpp
ErrorCode const ErrorOutOfMemory = ErrorCode("OUT OF MEMORY");
The big switch is not that bad for this. To get a string for an error code is almost always not performance critical.
You should keep in mind that these error strings are probably not what you want to show your users. The messeges for the user should be kept in resources for easier translation.
strings for error codes are for logs or diagnostics and need no translation.
You can use this trick to define your error codes and the strings in parrallel:
#if defined(ERROR_BUILD_ARRAY)
#define ERROR_START \
static const err_defn error_table[] = { \
{ WARNING, "Warning" },
#define ERRDEF(num, offset, str) { num, str },
#define ERROR_END { 0, NULL } };
#elif !defined(ERROR_ENUM_DEFINED)
#define ERROR_START \
typedef enum svn_errno_t { \
WARNING = OS_START_USERERR + 1,
#define ERRDEF(num, offset, str) /** str */ num = offset,
#define ERROR_END ERR_LAST } svn_errno_t;
#define ERROR_ENUM_DEFINED
ERROR_START
ERRDEF(ERR_BAD_BAD,
ERR_BAD_CATEGORY_START + 0,
"Bad error")
ERRDEF(ERR_BAD_FILENAME,
ERR_BAD_CATEGORY_START + 1,
"Bogus filename")
ERROR_END
(Copied from subversion sources)
I tend to avoid the switch since it's usually a big piece of code. I prefer a table lookup along the lines of:
In btree.h:
enum btreeErrors {
ZZZ_ERR_MIN = -1,
OKAY,
NO_MEM,
DUPLICATE_KEY,
NO_SUCH_KEY,
ZZZ_ERR_MAX };
In btree.c:
static const char *btreeErrText[] = {
"Okay",
"Ran out of memory",
"Tried to insert duplicate key",
"No key found",
"Coding error - invalid error code, find and destroy developer!"
};
const char *btreeGetErrText (enum btreeErrors err) {
if ((err <= ZZZ_ERR_MIN) || (err >= ZZZ_ERR_MAX))
err = ZZZ_ERR_MAX;
return btreeErrText[err];
}
Not that it usually matters since errors should be the exception rather than the rule, but table lookups are generally faster than running big switch statements (unless they get heavily optimised).
I wanted a way to have error code (int) and string description (any string) be declared in one and only one single place and none of the examples above allows that (ERR_OK has to be declared somewhere and then "ERR_OK" is mapped to it somewhere else).
So I declared a simple class storing both int and string and maintaining a static map for int->string conversion. I also added an "auto-cast to" int function:
class Error
{
public:
Error( int _value, const std::string& _str )
{
value = _value;
message = _str;
#ifdef _DEBUG
ErrorMap::iterator found = GetErrorMap().find( value );
if ( found != GetErrorMap().end() )
assert( found->second == message );
#endif
GetErrorMap()[value] = message;
}
// auto-cast Error to integer error code
operator int() { return value; }
private:
int value;
std::string message;
typedef std::map<int,std::string> ErrorMap;
static ErrorMap& GetErrorMap()
{
static ErrorMap errMap;
return errMap;
}
public:
static std::string GetErrorString( int value )
{
ErrorMap::iterator found = GetErrorMap().find( value );
if ( found == GetErrorMap().end() )
{
assert( false );
return "";
}
else
{
return found->second;
}
}
};
Then, you simply declare your error codes as below:
static Error ERROR_SUCCESS( 0, "The operation succeeded" );
static Error ERROR_SYSTEM_NOT_INITIALIZED( 1, "System is not initialised yet" );
static Error ERROR_INTERNAL( 2, "Internal error" );
static Error ERROR_NOT_IMPLEMENTED( 3, "Function not implemented yet" );
Then, any function returning int can do to return 1
return ERROR_SYSTEM_NOT_INITIALIZED;
And, client programs of your library will get "System is not initialised yet" when calling
Error::GetErrorString( 1 );
The only limitation I see is that static Error objects are created many times if .h file declaring them is included by many .cpp (that's why I do a _DEBUG test in constructor to check consistency of the map). If you don't have thousands of error code, it should be a problem (and there may be a workaround...)
Jean

Whats the right approach to return error codes in C++

I'm using error codes for handling errors in my c++ project. The problem is how to return error codes from a function which is supposed to return some variable/object.
consider this:
long val = myobject.doSomething();
Here, myobject is an object of some class. If doSomething function encounters some error condition then how should it notify the caller (Without using exceptions).
Possible solutions:
Have a data member (say err_) in the class which can be checked by the caller. But it would be unsafe in a multi-threaded application sharing the same object and calling the same function.
Use some global error variable, again same issue in a multi-threaded environment.
Now how can I notify the caller about some error condition?
Make a template called, say, Maybe that it parametrized by your return value type. Whenever you return a value, wrap it in this template like this:
Maybe<long> result = object.somemethod();
The Maybe template would have a way of being instantiated with an error code (probably a static method):
return Maybe<long>::error(code);
But ordinarily would just be returned with the value:
Maybe<long> retval;
retval = 15;
return retval;
(You would have to, of course, override the appropriate constructors, assignment operators, etc.)
In the client side you call a method to check for the error.
Maybe<long> result = object.somemethod();
if (result.is_error)
{
... handle the error ...
}
else
{
... use the result ...
}
Again you'd need the appropriate operators defined to use Maybe<long> wherever there's a long required.
This sounds like a lot of work, but really the work is done once in making a good, bulletproof Maybe template. You'll also have to do some performance tuning on it to avoid nasty overheads. If you want to make it more flexible you can parametrize it on both the return value type and the error type. (This is only a minor increase in complexity.)
You probably want something like Alexandresu's Expected<T> idiom.
You can pass variable as reference and return error code in it.
You can return a std::pair holding both an error code (or error object) and the desired return object. The object of interest needs a default constructor or value so you can return something even when an error is encountered.
It is common to return a return/error code, and make available a property or member with the results.
int retCode = myobject.doSomething();
if (retCode < 0){ //Or whatever you error convention is
//Do error handling
}else{
long val = myobject.result;
}
It is also common to pass in a pointer that is set to the return value, and return the return/error code. (See HrQueryAllRows).
long val = INIT_VAL;
int retCode = myObject.doSomething(&val);
if (retCode < 0){
//Do error handling
}else{
//Do something with val...
}
You have three options:
Create a class containing the return value and a possible error code.
Use something like boost::optional for the return value, which allows
for invalid responses.
Pass a reference to a variable and return any possible error code
within that.
I see there are many nice solutions, but I approach it in another way if I have this situation.
auto doSomething()
{
// calculations
return std::make_pair(error_code, value)
}
int main()
{
auto result = doSomething();
if (!result.first)
{
std::cout << result.second;
}
else
{
std::cout << "Something went wrong: " << result.second;
}
}
For me it's a clean solution than passing bool as reference. auto return type deduction is supported from c++14
Return an error handle. Have an error manager keep the error codes and additional informations (e.g. ERROR_INVALID_PARAMETER and name-value-pairs like ParameterName="pszFileName"). This information can be accessed using the handle. The caller can check the error handle against a NO_ERROR_HANDLE. If true, no error occurred. The caller can augment the error information and pass the handle up the stack.
The error manager can be one for the process or one for each thread.
I would suggest following:
class foo {
public:
long doSomething();
long doSomething(error_code &e);
};
Where error_code is some type that holds error. It may be integer or better something based on boost::system::error_code.
And you supply two functions:
First version throws the error, for example throw boost::system::system_error that is created from boost::system::error_code.
Second returns the error code into e.
The most common practice is to return the error code
long result;
int error = some_obj.SomeMethod(&result);
or return a value that indicate there was an error:
long result = some_obj.SomeMethod();
if (result < 0) error = some_obj.GetError();
In C++17 you use std::optional from the <optional> header:
std::optional<long> myobject = some_func(some_bool);
if (myobject.has_value()) {
// do stuff with myobject.value()
} else {
// myobject has no value
}
// ...
// Example function that returns an optional
std::optional<long> some_func(bool b) {
if (b)
return 15;
return {};
}
define all the error codes in a File. based on error category you can return the error code and the caller can decide what went wrong and caller can return its own error code.
for example
#define FILE_ERROR 1
#define SANITY_ERROR 2
int WriteToFile(char* Data, int iErrorCode)
{
char* FileName;
if (!FileOpen(FileName, &iErrorCode))
{
//Analyze error code and make decision on what to ignore or terminate
iErrorCode = FILE_ERROR;
return 0;
}
}
int FileOpen(char* FileName, int* iErrorCode)
{
if (FileName == null)
{
iErrorCode = SANITY_ERROR;
return 0;
}
///// next code blocks
return 1;
}
I found a new way to do it. It is non-standard and this is an entirely new way to do it.
So consider using this approach cautiously.
Use the following header file:
SetError.h:
#include <string> // for string class
#ifndef SET_ERROR_IS_DEFINED
#define SET_ERROR_IS_DEFINED
class Error {
public:
int code = 0;
std::string errorMessage;
std::string fileName;
std::string functionName;
Error() {}
Error(int _errorCode, std::string _functionName = "", std::string _errorMessage = "", std::string _fileName = "")
{
code = _errorCode;
functionName = _functionName;
errorMessage = _errorMessage;
fileName = _fileName;
}
};
#if defined(_DEBUG) || !defined(NDEBUG)
#define ___try { _ERROR.code = 0; bool __valid_try_mode_declared;
#define ___success }
#define SetError(pErrorData) __valid_try_mode_declared = true; _ERROR = *pErrorData; delete pErrorData;
#else
#define ___try { _ERROR.code = 0;
#define ___success }
#define SetError(pErrorData) _ERROR = *pErrorData; delete pErrorData;
#endif
#endif
inline Error _ERROR;
Include it everyware.
Example of how to use:
Main.cpp:
#include "SetError.h"
#include <iostream>
bool SomeFunction(int value) ___try;
{
if (value < 0) {
SetError(new Error(10, "SomeFunction", "Some error", "File main.cpp"));
return false;
}
return true;
} ___success; // You mast to warp the function with both ___try and ___success
// These keywords must be at the start and the end of the function!
int main()
{
using namespace std;
bool output = SomeFunction(-1);
if (_ERROR.code != 0) { // This is how you check the error code. using the global _ERROR object
cout << "error code: " << _ERROR.code << ", from function: "
<< _ERROR.functionName << ", from file: " << _ERROR.fileName;
}
cout << endl << "Founction returned: " << output << endl;
return 1;
}
If you have some functions that run in another thread, these functions need to be inside namespace and then you can do this:
namespace FunctionsInSomeThread
{
#include "SetError.h"
bool SomeFunc1() ___try;
{
SetError(new Error(5, "SomeFunction2", "Some error from another thread", "File main.cpp"))
return true;
} ___success;
bool SomeFunc2() ___try;
{
SetError(new Error(5, "SomeFunction2", "Some error from another thread", "File main.cpp"))
return true;
} ___success;
}
And to access _Error, you need to add the namespace of the thread
if (FunctionsInSomeThread::_ERROR.code != 0)
{
// Error handling
}
Or in case it is inside the same namespace then no need to add FunctionsInSomeThread:: before.
The idea behind this is that you can't warp the function only with ___success; keyword. You will get compile error. So the developer will never return old error code from another function.
If you wrote ___success; at the end of the codeblock, you must write also ___try; at the start!
You also can't use SetError macro if it is not wrapped in ___try; and ___success;.
The idea come from the AutoIt language where you have this consept:
https://www.autoitscript.com/autoit3/docs/functions/SetError.htm
So this is almost the same in C if you use this header.

C++ null string

I have a function in a C++ program returning a string.
On certain conditions, e.g. if the function encounters an error or so, I want to return a special value telling the caller that something has gone wrong.
I could basically just return an empty string "", but the function does need the empty string as normal return value.
How can I accomplish this?
Do I have do create a special data structure that for my function that holds a bool if the function was successfully run and a string containing the actual return value?
This sounds like a usecase for exceptions.
try {
std::string s = compute();
} catch(ComputeError &e) {
std::cerr << "gone wrong: " << e.what();
}
If you don't want to or can't use exceptions, you could change the function's interface
std::string result;
if(!compute(result)) {
std::cerr << "Error happened!\n";
}
Though most often, i've seen the return value is used for the actual result, and an error pointer is passed
bool b;
std::string s = compute(&b);
if(!b) {
std::cerr << "Error happened!\n";
}
This has the benefit that you can default the error argument pointer to 0 and code that can ignore the error (because it could live with an empty string return, for example, or if it knows in advance the input is valid) would not need to bother:
std::string compute(bool *ok = 0) {
// ... try to compute
// in case of errors...
if(ok) {
*ok = false;
return "";
}
// if it goes fine
if(ok) {
*ok = true;
}
return ...;
}
You can definitely return a pair, although it is klunky.
pair< string, bool > my_method(...) {
if (a) {
return make_pair(some_value, true);
} else {
return make_pair("", false); // error
}
}
pair< string, bool > result = my_method(...);
if (result.second) {
// success
} else {
// error
}
You can also pass either the bool or the string by reference,
bool my_method(string& s, ...) {
...
}
string s;
if (my_method(s, ...)) {
// success
} else {
// error
}
or:
string my_method(bool& ok, ...) {
ok = false; // default
...
}
bool ok;
s = my_method(ok, ...));
if (ok) {
// success
} else {
// error
}
You could try returning an auto_ptr to a string, but this will cost you an explicit new-ing of a string.
std::auto_ptr<std::string> Foo(int i)
{
if(i == 0) // Error!
return std::auto_ptr<std::string>(NULL);
else // Works.
return std::auto_ptr<std::string>(new string("Hello world!"));
}
If it's really something like an error, you should throw an exception. But by reading your question I guess it's not an "exceptional behaviour"?
If that's the case, you have several non-perfect solutions :
Return a structure with the string and a boolean that tells if the function failed (a simple std::pair<> could be enough).
Make your function modify a string parameter provided by reference and return a boolean telling if the function failed.
Make your function a functor/object that have a state. That state would be (at least) a boolean giving the failure or success of the last function call -- that would then be a function call.
3 is IMO bad design, while 2 and 1 are unperfect compromise.
It depends on how is your program organized.
You may return an additional boolean signifying if the function succeeded. You may return a structure containing boolean and string. You may return a special string (not necessarily empty) which should represent the failure. You may throw an exception. You may set a global flag indicating an error (though I would not recommend it).
There must be lot of other methods to express function failure, too.
The std::pair<> method is good. Another alternative is to have the caller pass the output string in as a non-const reference, and have the function return true or false depending on if an error was encountered or not.
bool Foo(int i, std::string& result)
{
bool ret = false; // no error
// do stuff...
result = "blahbalhbalh";
return ret;
}