Check a value at compile time if possible - c++

I'd like to check a value at compile time, if it's a constexpr value and do run a constexpr form-checking function on it if it is.
Can I do this in c++11/14?
In pseudo code, I'd like to do:
static_if (is_constexpr(x))
static_assert(check(x))
Details:
I'm checking a string for a particular format. It's conceptually:
template<std::size_t N>
constexpr bool check(const char (&s)[N]){ return true; }
//^ really a recursive call that checks the string
The constexpr check works with a string literal, but not with a string pointer:
int main(){
const char* s = "#";
static_assert(check("#"), "Fmt");; //OK
//This fails; expectation was it suceeds and the check doesn't run
static_assert(!is_constexpr(s) || check(s), "Fmt");
}
The is_constexpr is:
#include <type_traits>
template<typename T>
constexpr typename std::remove_reference<T>::type makeprval(T && t) {
return t;
}
#define is_constexpr(e) noexcept(makeprval(e))

May be your question is bit unclearer to me. If you want whether a string literal should pass and pointer should not then look at below answer. Should you feel that, I have misunderstood your question then comment it, I shall delete this answer or modify accordingly.
You can use simple C-style macro to check if given variable is a string literal, as I have explained in my answer to below question:
Verify type of string (e.g. literal, array, pointer) passed to a function
#define IS_LITERAL(X) "" X
The compilation will fail if the X is not a string literal.

Related

static_assert in a macro but also expand to something that can be used as a function parameter

For instance. I have the macro CHARCOUNT(x) that expands to sizeof(x)/sizeof(x[0]). I would like to use static_assert to ensure each macro expansion does a check to see if the result is greater than 2 to avoid someone passing in a pointer to a string and not pointer to an array of characters.
I would like something like this static assert:
static_assert(x) > 2
This macro would be used to ensure that string copies don't exceed the buffer size such as:
TCHAR szMyStr[10];
_tcscpy_s(szMyStr, CHARCOUNT(szMyStr), L"My result");
If someone accidentally passes in a pointer where CHARCOUNT would result in the length of the pointer to the string instead of the number of bytes I would like an assert at compile time.
const TCHAR* myChars = L"My result";
auto len = CHARCOUNT(myChars);
The CHARCOUNT above should result in a compile time assert.
Any pointers would be helpful.
You should be using std::extent instead of that macro, which gives you 0 for unsupported types (e.g. arrays without bounds, non-array types).
For your use case a constexpr function that gives you the size for an array variable would be better suited, like so:
template <typename T, std::size_t N>
constexpr std::size_t arrsize(T (&)[N]) {
return N;
}
Then you don't need to assert on the size since you can only use the function with actual arrays.

When does the prefix L matters for char or wchar_t literal?

Most times that I forget the L prefix for a wchar_t literal, or that I put one by mistake for a char literal, it seems that compilation (g++) doesn't complain (no error, no warning) and that my program acts as intended.
for example
char cString[] = "Hello World!";
*std::strchr(cString, L'W') = L'w';
std::cout << cString << std::endl;
and
wchar_t cWideString[] = L"Hello World!";
*std::wcschr(cWideString, 'W') = 'w';
std::wcout << cWideString << std::endl;
both work.
Is it because, in this case, 'W' and 'w' are single-byte characters?
I'm interested, because I would like to use this on purpose, for functions like:
template<typename T> T* findNextSpace(T* str);
intended to be used for for T equal to char, const char, wchar_t, or const wchar_t. Would it be safe to use ' ' in the definition of such a function, for any character type T?
Or should I use something like (T) in order to cast the literal to the correct type?
EDIT: I know it makes a difference for char* and wchar_t*, but my question is not about string literals, it is about character literals.
Both cases fall under the rules for implicit conversions. Specifically the rules for integral conversions. The implicit conversion of char to whar_t should be well defined for all cases, as wchar_t is at least as wide as a char. Your compiler might warn you of the risk of data loss in the conversion from wchar_t to char, if the value of the wchar_t is (or can be in case the value isn't known at compile time) outside the range representable by char.
From my understanding the integer conversion rules applies to prvalue expressions of an integer type, characters are of integer type, and literals (except string literals) are prvalues, so this is why you see the behavior you see with the character literals, while you don't see it with string literals.
I don't have a version of the standard that I can look things up in, but I understand that cppreference is found to be a reasonable source of information. Hopefully it is accurate and I interpreted the rules correctly.
As for your question regarding finding the next space, you should probably split that into a separate question. With that said you should probably use std::isspace/std::iswspace (Unless you specifically only want ' '), and then have the compiler select the appropriate function based on T:
#include <type_traits>
#include <cwctype>
#include <cctype>
template <class T>
T* findNextSpace(T* str) {
if constexpr(std::is_same_v<T, char>) {
//Use std::isspace
}
else if(std::is_same_v<T, wchar_t>) {
//Use std::iswspace
}
else {
static_assert("Not implemented");
}
}
In case your compiler doesn't support the features used here, you can implement a similar solution using template specialization:
#include <cwctype>
#include <cctype>
template <class T>
struct isspace_helper;
template <>
struct isspace_helper<char> {
bool operator()(char c) const {
return std::isspace(c);
}
};
template <>
struct isspace_helper<wchar_t> {
bool operator()(wchar_t c) const {
return std::iswspace(c);
}
};
Obviously you could also use this with std::string as well (Because most people would suggest you used std::string instead over char/wchar_t arrays unless you have a good reason not to):
#include <algorithm>
#include <string>
template <class CharT, class Traits, class Alloc>
auto findNextSpace(std::basic_string<CharT, Traits, Alloc>& str) {
return std::find(str.begin(), str.end(), isspace_helper<CharT>{});
}
If your compiler doesn't support auto you can write std::basic_string<CharT, Traits, Alloc>::iterator instead. Then maybe provide an overloading accepting the string by const-reference for good measure.

Detecting string literals at compile time [duplicate]

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, "")

Is there a way to determine if a parameter is a literal string? [duplicate]

This question already has answers here:
Can I determine if an argument is string literal?
(11 answers)
Closed 9 years ago.
My question is:
Is there a way to determine whether a parameter is a literal string or not?
template<class T>
bool IsLiteral(T arg)
{
// How to implement?
}
or
template<class T>
struct IsLiteral { enum { value = ??? }; };
So that we can write the following code:
char* p = "Hello";
assert(IsLiteral(p)); // fail.
assert(IsLiteral("Hello")); // never fail.
assert(IsLiteral<decltype("Hello")>::value); // never fail.
There is no way to detect string literals. What can be detected is that argument is a fixed size array of char const:
template <std::size_t N>
bool IsLiteral(char const (&)[N]) {
return true;
}
template <std::size_t N>
bool IsLiteral(char (&)[N]) {
return false;
}
template <typename T>
bool IsLiteral(T) {
return false;
}
I don't think you can distinguish between these two uses, however:
char const array[] = { 'a' };
IsLiteral(array);
IsLiteral("foo");
Is there a way to determine whether a parameter is a literal string or not?
I don't think so, a string literal is prepocessing token and will be turned into an array of const char, so you won't be able to distinguish if such as array came from a string literal or not. If we look at the C++ draft standard section 2.14.5 String literals paragraph 8 says:
Ordinary string literals and UTF-8 string literals are also referred to as narrow string literals. A narrow string literal has type “array of n const char”, where n is the size of the string as defined below, and has static storage duration.
"String Literal" is a source code term. Once the code is compiled it assigns/loads it into a memory location. The code using its value doesn't care or know if it was created at runtime or compiled time.

Restrict passed parameter to a string literal

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, "")