Is this a valid use of a const_cast ? I am using it in a constructor and it looks as follows:
KeyLiteObject(const char * extension, const char * swap_suffix)
: _extension(extension),
_swap_suffix(swap_suffix),
_swap_suffix_extension(swap_suffix)
{
const_cast<std::string*>(&_swap_suffix_extension)->append(_extension);
}
Yes, the strings will never change.
Assuming that _swap_suffix_extension is a const std::string then why not just do this:
KeyLiteObject(const char * extension, const char * swap_suffix)
: _extension(extension),
_swap_suffix(swap_suffix),
_swap_suffix_extension( std::string( swap_suffix ) + std::string( extension ) )
{
}
Then you can totally avoid the const_cast ...
Whenever possible avoid the const_cast, and here it is quite possible for any given type. Just create a helper function that takes the two arguments, composes the final value of the constant and use it in the initializer:
// header file
struct test {
const type x;
test( type const & a, type const & b );
};
// implementation file
namespace {
type compose( type const & arg1, type const & arg2 ) {
// calculate the actual value here
}
}
test::test(type const & a, type const & b)
: x( compose(a,b) )
{}
The cost of that is just writting a single free (static or in an unnamed namespace) function in the implementation file, and the result it readable if you choose a proper name for the function. In your case: concatenate or concat would be good choices.
While the use of const_cast in the example will not lead to undefined behavior, I would avoid it for personal reasons. Casts are cumbersome to write in C++ (compare with C or Java) for a reason: so that they will call the attention of the programmer: something weird is going on here! If you start sprinkling casts, then you will get used to seeing them, and they will become natural.
Related
I have a class to wrap string literals and calculate the size at compile time.
The constructor looks like this:
template< std::size_t N >
Literal( const char (&literal)[N] );
// used like this
Literal greet( "Hello World!" );
printf( "%s, length: %d", greet.c_str(), greet.size() );
There is problem with the code however. The following code compiles and I would like to make it an error.
char broke[] = { 'a', 'b', 'c' };
Literal l( broke );
Is there a way to restrict the constructor so that it only accepts c string literals? Compile time detection is preferred, but runtime is acceptable if there is no better way.
There is a way to force a string literal argument: make a user defined literal operator. You can make the operator constexpr to get the size at compile time:
constexpr Literal operator "" _suffix(char const* str, size_t len) {
return Literal(chars, len);
}
I don't know of any compiler that implements this feature at this time.
Yes. You can generate compile time error with following preprocessor:
#define IS_STRING_LITERAL(X) "" X ""
If you try to pass anything other than a string literal, the compilation will fail. Usage:
Literal greet(IS_STRING_LITERAL("Hello World!")); // ok
Literal greet(IS_STRING_LITERAL(broke)); // error
With a C++11 compiler with full support for constexpr we can use a constexpr constructor using a constexpr function, which compiles to a non-const expression body in case the trailing zero character precondition is not fulfilled, causing the compilation to fail with an error. The following code expands the code of UncleBens and is inspired by an article of Andrzej's C++ blog:
#include <cstdlib>
class Literal
{
public:
template <std::size_t N> constexpr
Literal(const char (&str)[N])
: mStr(str),
mLength(checkForTrailingZeroAndGetLength(str[N - 1], N))
{
}
template <std::size_t N> Literal(char (&str)[N]) = delete;
private:
const char* mStr;
std::size_t mLength;
struct Not_a_CString_Exception{};
constexpr static
std::size_t checkForTrailingZeroAndGetLength(char ch, std::size_t sz)
{
return (ch) ? throw Not_a_CString_Exception() : (sz - 1);
}
};
constexpr char broke[] = { 'a', 'b', 'c' };
//constexpr Literal lit = (broke); // causes compile time error
constexpr Literal bla = "bla"; // constructed at compile time
I tested this code with gcc 4.8.2. Compilation with MS Visual C++ 2013 CTP failed, as it still does not fully support constexpr (constexpr member functions still not supported).
Probably I should mention, that my first (and preferred) approach was to simply insert
static_assert(str[N - 1] == '\0', "Not a C string.")
in the constructor body. It failed with a compilation error and it seems, that constexpr constructors must have an empty body. I don't know, if this is a C++11 restriction and if it might be relaxed by future standards.
No there is no way to do this. String literals have a particular type and all method overload resolution is done on that type, not that it's a string literal. Any method which accepts a string literal will end up accepting any value which has the same type.
If your function absolutely depends on an item being a string literal to function then you probably need to revisit the function. It's depending on data it can't guarantee.
A string literal does not have a separate type to distinguish it from a const char array.
This, however, will make it slightly harder to accidentally pass (non-const) char arrays.
#include <cstdlib>
struct Literal
{
template< std::size_t N >
Literal( const char (&literal)[N] ){}
template< std::size_t N >
Literal( char (&literal)[N] ) = delete;
};
int main()
{
Literal greet( "Hello World!" );
char a[] = "Hello world";
Literal broke(a); //fails
}
As to runtime checking, the only problem with a non-literal is that it may not be null-terminated? As you know the size of the array, you can loop over it (preferable backwards) to see if there's a \0 in it.
I once came up with a C++98 version that uses an approach similar to the one proposed by #k.st. I'll add this for the sake of completeness to address some of the critique wrt the C++98 macro.
This version tries to enforce good behavior by preventing direct construction via a private ctor and moving the only accessible factory function into a detail namespace which in turn is used by the "offical" creation macro. Not exactly pretty, but a bit more fool proof. This way, users have to at least explicitly use functionality that is obviously marked as internal if they want to misbehave. As always, there is no way to protect against intentional malignity.
class StringLiteral
{
private:
// Direct usage is forbidden. Use STRING_LITERAL() macro instead.
friend StringLiteral detail::CreateStringLiteral(const char* str);
explicit StringLiteral(const char* str) : m_string(str)
{}
public:
operator const char*() const { return m_string; }
private:
const char* m_string;
};
namespace detail {
StringLiteral CreateStringLiteral(const char* str)
{
return StringLiteral(str);
}
} // namespace detail
#define STRING_LITERAL_INTERNAL(a, b) detail::CreateStringLiteral(a##b)
/**
* \brief The only way to create a \ref StringLiteral "StringLiteral" object.
* This will not compile if used with anything that is not a string literal.
*/
#define STRING_LITERAL(str) STRING_LITERAL_INTERNAL(str, "")
EDIT: As I was writing the question I noticed that the method std::string GetNodeValue(const std::string& nodePath, const char * defaultValue) wasn't const. As LogicStuff also mentioned in his comment, adding the const qualification resolved the ambiguity.
I know this question was already been asked and answered properly here and several other times. I understand the underlying problem but I can't quite figure out why it is happening in this particular case and it has awoken my curious self.
I have the following class:
class ConfigurationReader
{
public:
// ...
std::string GetNodeValue(const std::string& nodePath, const char * defaultValue)
{
const std::string temp(defaultValue);
return GetNodeValue(nodePath, temp);
}
template <typename T> T GetNodeValue(const std::string & nodePath, T defaultValue) const
{
boost::optional<T> nodeValue = configuration.getNodeValueNothrow<T>(nodePath);
if ( nodeValue )
{
return *nodeValue;
}
LogConfigurationProblemsCri(logger, "Node not found: " << nodePath << ", Default value: " << defaultValue);
return defaultValue;
}
// ...
};
The template method has also several specializations for the types int16_t, uint16_t, and so on up to uint64_t.
It works like a charm when used:
string someValue = configurationReaderPtr->GetNodeValue("some_noe", "");
uint32_t otherValue = configurationReaderPtr->GetNodeValue("other_node", 11000);
bool yetAnother = configurationReaderPtr->GetNodeValue("other_node", true);
Except in one case:
uint32_t otherValue = configurationReaderPtr->GetNodeValue("other_node", 0);
The error I keep getting is:
"2 overloads have similar conversions
could be 'std::string ConfigurationReader::GetNodeValue(const std::string &,const char *)' or 'uint32_t ConfigurationReader::GetNodeValue(const std::string &,uint32_t) const'"
I tried casting the "default" value: uint32_t(0), static_cast<uint32_t>(0), 0U without any luck.
I should point out that I already found a workaround:
uint32_t otherValue = 0;
otherValue = configurationReaderPtr->GetNodeValue("other_node", otherValue);
But this doesn't answer my curiosity. I am currently using Microsoft Visual Studio 2012 Express and boost 1.54 libraries.
Any thoughts?
This is, because 0 is the literal for an empty pointer (which in modern C++ is replaced by "nullptr").
So 0 can be either an int or an empty pointer, especially a char*
Edit to add some reference:
You can find this in the standard as
4.10 Pointer conversions
A null pointer constant is an integer literal (2.13.2) with value zero or a prvalue of type std::nullptr_t
(the last one is the reference to nullptr)
Both overloads are considered equally viable for
configurationReaderPtr->GetNodeValue("other_node", 0);
because:
requires an implicit conversion from 0, which is of type int to const char *.
requires an implicit conversion from ConfigurationReader* to ConfigurationReader const* (to call const-qualified member function)
After making both overloads (equally) const-qualified, the code compiles (the function template is preferred). The 1st overload also does not modify any members in the first place.
Live on Coliru
In your particular example, it seems prudent to change signature of string version to
std::string GetNodeValue(const std::string& nodePath, const std::string defaultValue)
This will remove any ambiguity.
I wrote the following but for some reason calling InstructionVal(b) is invalid.
intellisense is spitting out:
Only () is allowed for initializer member NPPInstructionDef::InstructionVal
here is the offending code:
//Single Instruction Definition for Instruction Dictionary
typedef struct NPPInstructionDef
{
const char* InstructionName;
const unsigned char* InstructionVal[];
NPPInstructionDef(const char* a, const unsigned char* b[]): InstructionName(a), InstructionVal()
{
}
}NPPInstruction;
Any Ideas? Thanks.
First, I'm assuming your initialization is InstructionVal(
b ), rather than the InstructionVal() which you've written.
But even then, what you've written shouldn't compile.
This is the usual problem, due to the fact that C style arrays
are broken, and shouldn't be used. Your definition:
unsigned char const* InstructionVal[];
defines an array of unknown length (thus, illegal in a class
defintion) of unsigned char*. There's no way to initialize
this in an initialization list, except by () (value
initialization).
What you want is:
std::vector <unsigned char*> InstructionVal;
, and the constructor should be:
NPPInstructionDef( std::string const& a,
std::vector <unsigned char> const& b );
, or perhaps more likely:
template <typedef Iterator>
NPPInstructionDef( std::string const& a,
Iterator begin,
Iterator end )
: InstructionName( a )
, InstructionDef( begin, end )
{
}
(This supposes, of course, that InstructionName is
std::string, instead of char const*. Which will avoid any
issues of lifetime of the string, for example, and allow easy comparison, etc.)
I have a class to wrap string literals and calculate the size at compile time.
The constructor looks like this:
template< std::size_t N >
Literal( const char (&literal)[N] );
// used like this
Literal greet( "Hello World!" );
printf( "%s, length: %d", greet.c_str(), greet.size() );
There is problem with the code however. The following code compiles and I would like to make it an error.
char broke[] = { 'a', 'b', 'c' };
Literal l( broke );
Is there a way to restrict the constructor so that it only accepts c string literals? Compile time detection is preferred, but runtime is acceptable if there is no better way.
There is a way to force a string literal argument: make a user defined literal operator. You can make the operator constexpr to get the size at compile time:
constexpr Literal operator "" _suffix(char const* str, size_t len) {
return Literal(chars, len);
}
I don't know of any compiler that implements this feature at this time.
Yes. You can generate compile time error with following preprocessor:
#define IS_STRING_LITERAL(X) "" X ""
If you try to pass anything other than a string literal, the compilation will fail. Usage:
Literal greet(IS_STRING_LITERAL("Hello World!")); // ok
Literal greet(IS_STRING_LITERAL(broke)); // error
With a C++11 compiler with full support for constexpr we can use a constexpr constructor using a constexpr function, which compiles to a non-const expression body in case the trailing zero character precondition is not fulfilled, causing the compilation to fail with an error. The following code expands the code of UncleBens and is inspired by an article of Andrzej's C++ blog:
#include <cstdlib>
class Literal
{
public:
template <std::size_t N> constexpr
Literal(const char (&str)[N])
: mStr(str),
mLength(checkForTrailingZeroAndGetLength(str[N - 1], N))
{
}
template <std::size_t N> Literal(char (&str)[N]) = delete;
private:
const char* mStr;
std::size_t mLength;
struct Not_a_CString_Exception{};
constexpr static
std::size_t checkForTrailingZeroAndGetLength(char ch, std::size_t sz)
{
return (ch) ? throw Not_a_CString_Exception() : (sz - 1);
}
};
constexpr char broke[] = { 'a', 'b', 'c' };
//constexpr Literal lit = (broke); // causes compile time error
constexpr Literal bla = "bla"; // constructed at compile time
I tested this code with gcc 4.8.2. Compilation with MS Visual C++ 2013 CTP failed, as it still does not fully support constexpr (constexpr member functions still not supported).
Probably I should mention, that my first (and preferred) approach was to simply insert
static_assert(str[N - 1] == '\0', "Not a C string.")
in the constructor body. It failed with a compilation error and it seems, that constexpr constructors must have an empty body. I don't know, if this is a C++11 restriction and if it might be relaxed by future standards.
No there is no way to do this. String literals have a particular type and all method overload resolution is done on that type, not that it's a string literal. Any method which accepts a string literal will end up accepting any value which has the same type.
If your function absolutely depends on an item being a string literal to function then you probably need to revisit the function. It's depending on data it can't guarantee.
A string literal does not have a separate type to distinguish it from a const char array.
This, however, will make it slightly harder to accidentally pass (non-const) char arrays.
#include <cstdlib>
struct Literal
{
template< std::size_t N >
Literal( const char (&literal)[N] ){}
template< std::size_t N >
Literal( char (&literal)[N] ) = delete;
};
int main()
{
Literal greet( "Hello World!" );
char a[] = "Hello world";
Literal broke(a); //fails
}
As to runtime checking, the only problem with a non-literal is that it may not be null-terminated? As you know the size of the array, you can loop over it (preferable backwards) to see if there's a \0 in it.
I once came up with a C++98 version that uses an approach similar to the one proposed by #k.st. I'll add this for the sake of completeness to address some of the critique wrt the C++98 macro.
This version tries to enforce good behavior by preventing direct construction via a private ctor and moving the only accessible factory function into a detail namespace which in turn is used by the "offical" creation macro. Not exactly pretty, but a bit more fool proof. This way, users have to at least explicitly use functionality that is obviously marked as internal if they want to misbehave. As always, there is no way to protect against intentional malignity.
class StringLiteral
{
private:
// Direct usage is forbidden. Use STRING_LITERAL() macro instead.
friend StringLiteral detail::CreateStringLiteral(const char* str);
explicit StringLiteral(const char* str) : m_string(str)
{}
public:
operator const char*() const { return m_string; }
private:
const char* m_string;
};
namespace detail {
StringLiteral CreateStringLiteral(const char* str)
{
return StringLiteral(str);
}
} // namespace detail
#define STRING_LITERAL_INTERNAL(a, b) detail::CreateStringLiteral(a##b)
/**
* \brief The only way to create a \ref StringLiteral "StringLiteral" object.
* This will not compile if used with anything that is not a string literal.
*/
#define STRING_LITERAL(str) STRING_LITERAL_INTERNAL(str, "")
I have to write a library which contains a function that takes two strings parameters:
void foo(const std::string& arg1, const std::string& arg2);
My library is going to be used by some people that don't like C++ and are only used to const char*.
To satisfy their likes, I changed the prototype:
void foo(const char* arg1, const char* arg2);
And made my first version a simple inline call:
inline void foo(const std::string& arg1, const std::string& arg2)
{
foo(arg1.c_str(), arg2.c_str());
}
Of course, thanks to the std::string constructors, it would have worked almost the same way with just the first version. Writing this overload just avoids instanciating useless std::string in the case someone passes only const char*.
But now I wonder: is this overload really necessary or is it just premature optimization ?
Also, I'm feeling like this is somehow incomplete: should I write also void foo(const char* arg1, const std::string& arg2) and void foo(const std::string& arg1, const char* arg2) overloads ? What if I have 3, 4 or more (n) parameters ? Should I write 2n overloads ?
In short, have you ever faced a similar situation ? What choices did you made and why ?
Thank you.
IMO it's reasonable to have two overloads to handle two different programming styles that co-exist within your organization.
Technically it's not just an optimization:
the const char* can be extern "C", so might be useful for bindings from other languages, or even from other C++ code across a dll boundary with incompatible standard library implementation.
the conversion to std::string can throw bad_alloc, so if it cannot otherwise fail then the const char* version is useful if you have a C-style string and want to use it in a nothrow context.
Also beware that in principle c_str() can throw bad_alloc, but I doubt that any implementations actually do.
2n overloads doesn't seem worthwhile to me - if someone is mixing string and char* then it's not just a programming style difference, they're actually using mixed formats for some reason. Since they're using both already, they can convert for themselves.
This all assumes that the function is simple enough that you're happy to implement the actual work with const char* parameters. If the implementation based on string would be significantly simpler (for example if it takes significant code to make it exception-safe otherwise), then that probably wins over efficiency anyway, so don't provide any overloads, let their const char* convert to string.
As long as you want to work with C++ (and not in C), the second one seems unneccessary, if you've this:
void foo(const std::string& arg1, const std::string& arg2);
You can call this with all combinations of std::string and char* as:
char *ca, *cb;
std::string sa, sb;
//...
foo(ca,cb); //char*, char*
foo(sa,cb); //std:string, char*
foo(sa,sb); //std::string, std::string
foo(ca,sb); //char*, std::string
If const char * text is never null, you could use string, because it has implictit constructor, so string class version could be enough. In other hand: if const char * text could be null, it generates runtime error.
One more thing: on DLL interface STL is not really good option. So if the function is part of a DLL interface, you may use C style strings.
I may do it in that way:
#include <string>
using namespace std;
void foo( const string arg0, const string arg1 )
extern "C" _declspec( dllexport ) void foo( const char * arg0, const char * arg1 )
{
string string_arg0, string_arg1;
if ( arg0 != 0 )
string_arg0 = arg0;
if ( arg1 != 0 )
string_arg1 = arg1;
foo(string_arg0, string_arg1);
}
In that case, you could probably just have the (const char*,const char*) and ask everyone using std::string to use c_str(). That way there won't be any memory allocation overhead, only the extra c_str() that people will have to code up.
My library is going to be used by some people that don't like C++ and
are only used to const char*.
Tell them to man up and learn the language that their compiler compiles. You take std::string, because that's how to do it in C++, and if they don't like it, then they can get a C compiler.
I think your present approach is correct. Where you overload for const char* and provide a wrapper which also serves std::string.
If your colleagues are going to use C-style character pointer than it's better to do that way (present way). See following case;
char *p = 0;
foo(p);
void foo (const string &s)
{ // runtime error
}
Demo. As you can see that character pointers may not go well always with std::string; so why to take chance. Even though people may not do such coding; still you should avoid such potential hazards for long time maintainability.
Inside the function you can always choose to have std::string from const char* and write your algorithm.