Krcn U
Krcn U

Reputation: 421

Function determining its return type in C++

Trying to write a function that determines its own return type according to some preprocessor directives. But i am not sure if this is possible in C++.

type ConvertStrIfNecessary(){
    std::str mystr="abcdefghif";
    #ifdef MYCONDITION
    return mystr.c_str();
    #else
    return mystr;
    #endif

}

Upvotes: 1

Views: 91

Answers (2)

ilent2
ilent2

Reputation: 5241

If you want to do everything with preprocessor commands you could define your own string type

#ifdef MYCONDITION
#define STRING_TYPE const char*
#else
#define STRING_TYPE std::string
#end

Then your function would be

STRING_TYPE ConvertStrIfNecessary(){
    std::string mystr="abcdefghif";
    #ifdef MYCONDITION
    return mystr.c_str();
    #else
    return mystr;
    #endif
}

But, again, be careful with returning .c_str(). However, apart from the use of std::string, this is very much the C way of doing things, prefer a solution like auto if your using C++ (see Zeta's solution).

Upvotes: 1

Zeta
Zeta

Reputation: 105876

It depends on your compiler and whether it supports N3638 (g++ since 4.9):

/* 
vvvv "auto" is enough */
auto ConvertStrIfNecessary(){
    std::string mystr="abcdefghif";
    #ifdef MYCONDITION
    return mystr.c_str();
    #else
    return mystr;
    #endif
}

You need to enable C++14 with -std=c++14 in GCC. Keep in mind that C++14 support is still experimental. Note that this only works if all returns in your function return values of the same type. Since there's only one return after preprocessing it's fine in this case.

Your users could then use auto again:

auto theValue = ConvertStrIfNecessary();

That being said, your code yields undefined behaviour if you return mystr.c_str(), since the pointer returned by c_str() is invalidated when mystr goes out of scope.

Even worse, const char* and std::string have different semantics, and the code will most likely not compile later since some client used theValue as char*, where someone else used it as std::string.

If you really want different types, you could instead provide a common interface type:

#ifdef MYCONDITION
using stringlike_t = const char *;
#else
using stringlike_t = std::string;
#endif

That gives you control on the "safe" methods a user can use.

Upvotes: 4

Related Questions