Variadic templates vs vsnprintf - c++11

While attempting to upgrade the following function to C++11
int inline formatText(const char* const fmt, ...)
{
va_list args;
va_start(args, fmt);
int len = std::min(vsnprintf(m_text, m_textSize, fmt, args), m_textSize);
va_end(args);
m_text[len] = '\0'; // assume m_textSize is storage size - sizeof('\0')
return len;
}
Obviously since printf deals with PODs, it's not really a problem for this function to accept its arguments by value.
But I realized I wasn't clear on how to achieve macro-like exact forwarding of the arguments, I realize that by inlining a simple version of this the compiler can eliminate pass-by-value, but I'm not exactly sure which of the three following approaches is technically best:
template<typename... Args>
#if defined(APPROACH_1)
int formatText(const char* const fmt, Args...)
#elif defined(APPROACH_2)
int formatText(const char* const fmt, const Args&...)
#else
int formatText(const char* const fmt, Args&&...)
#endif
{
int len = std::min(snprintf(m_text, m_textSize, fmt, std::forward<Args>(args)...);
m_text[len] = '\0';
return len;
}
Since we're talking printf here, copy-by-value isn't terrible, because I shouldn't be passing it non-pod objects; specifying const ref would certainly help complex objects that I don't want copying but clearly is counter-productive for the normal use cases of printf. I'm plain not sure what the side-effects of approach 3 are.
Everything I've read so far has left me with the impression that 'Args&&...' is likely to be the normal case for variadic templates, but in this case my gut tells me to go for approach #1.

Related

How to use auto keyword to assign a variable of type uint32_t or uint64_t in C++

Consider auto var = 5u;. Here, I am using suffix u, so that var will be deduced as unsigned int. Is there any way to achieve something similar for uint32_t or uint64_t types? Is there any suffix in C++11 or C++14?
I'm assuming you're working with the AAA style suggested by Herb Sutter.
In that case, a nice solution is to simply write:
auto variable_name = uint64_t{ 5000000000 };
This is clear, consistent, and explicitly typed with no nasty C-preprocessor necessary.
Edit: if you want to be absolutely sure when using a literal, an appropriate suffix can be added to the integer literal to ensure great enough range, while still explicitly typing the variable.
You could always define your own suffix
#include <cstdint>
#include <type_traits>
uint32_t operator ""_u32 (unsigned long long v) { return uint32_t (v); }
int main ()
{
auto v = 10_u32;
static_assert (std::is_same <decltype (v), uint32_t>::value);
}

Optional throw in constexpr?

I was researching how to implement a compile time strlen for a toy project in this repo https://github.com/elbeno/constexpr when I noticed an unusual pattern of throws in some of the code. It seemingly does nothing, why would you do this?
namespace err {
extern const char * strlen_runtime_error;
}
constexpr int strlen(const char * str) {
return true ? constexpr_func() : throw strlen_runtime_error;
}
I got curious if it has any use what so ever but couldn’t find anything useful on my own. The extern err is undefined.
It seems it is trying to enforce the function being used only in compile time, according to this comment in another of the functions of the library:
// convenience function for inferring the string size and ensuring no
// accidental runtime encryption
template <uint64_t S, size_t N>
constexpr encrypted_string<S, N> make_encrypted_string(const char(&s)[N])
{
return true ? encrypted_string<S, N>(s) :
throw err::strenc_runtime_error;
}
However, as you point out, it is not doing anything here. Typically, that trick with the ternary operator in constexpr functions is used to trigger compile-time errors given a condition -- not to ensure all calls to the function are constant expressions. See constexpr error at compile-time, but no overhead at run-time for an explanation of that pattern.
If you need to ensure that the result was found out during compile time, you can easily assign the result to a constexpr variable:
constexpr int result = strlen("asd");

Overloaded "operator new" wants to see the type it's allocating

This seems like it ought to be obvious, but I'm blanking on it. I have
class SimpleMemoryPool {
char buffer[10000];
size_t idx;
void *Alloc(size_t nbytes) { idx += nbytes; return &buffer[idx - nbytes]; }
};
inline void* operator new (size_t size, SimpleMemoryPool& pool)
{
return pool.Alloc(size);
}
inline void* operator new[] (size_t size, SimpleMemoryPool& pool)
{
return pool.Alloc(size);
}
The idea is that I can allocate new objects out of my SimpleMemoryPool and then they'll all be "released" when the SimpleMemoryPool is destroyed:
void foo()
{
SimpleMemoryPool pool;
int *arr = new (pool) int[10];
double *arr2 = new (pool) double(3.14);
...do things with arr and arr2...
return; // and arr, arr2 are "released" at this point
}
One nitpick I've simplified away: The above code is sketchy because the double won't be 8-byte-aligned. Don't worry about that; my real SimpleMemoryPool code returns maxaligned chunks.
Here's the next thing you're probably thinking at this point: "Who calls the destructors?!" I.e., if I accidentally write
std::string *arr3 = new (pool) std::string;
then I'm in a world of hurt, because the compiler will generate a call to std::string::string() for me, but nobody will ever call std::string::~string(). Memory leaks, bad stuff follows.
This is the problem I want to solve. What I want to do is basically
class SimpleMemoryPool {
...
// (std::enable_if omitted for brevity)
template<typename T, typename... Args>
T *New(Args... args) {
static_assert(std::is_trivially_destructible<T>::value, "T must be trivially destructible!");
void *ptr = this->Alloc(nelem * sizeof (T));
return new (ptr) T(std::forward<Args>(args)...);
}
template<typename ArrayT>
auto NewArray(size_t nelem) -> std::remove_extent<ArrayT>::type {
typedef typename std::remove_extent<ArrayT>::type T;
static_assert(std::is_trivially_destructible<T>::value, "T must be trivially destructible!");
void *ptr = this->Alloc(nelem * sizeof (T));
return new (ptr) T[ nelem ];
}
};
...
int *arr = pool.NewArray<int>(10);
double *arr2 = pool.New<double>(3.14);
std::string *arr3 = pool.New<string>(); // fails the static_assert, hooray!
The problem with this approach is that it's ugly. It looks bad, and it invites later maintainers to come along and "fix" the code by adding a "proper" operator new, at which point we lose the safety of the static_assert.
Is there any way to get the best of both worlds — type-safety via the static_assert, and also a nice syntax?
You may assume C++11. I also welcome C++14 answers, even though they won't be immediately useful to me.
Adding a member operator new to all my classes (in this example int and double) is not acceptable. Whatever I do has to work out-of-the-box without changing a million lines of code.
This is probably a duplicate of Get type of object being allocated in operator new but I'd still like answers tailored to this particular use-case. There might be some nice idiom of which I'm not aware.

Deduced type of "auto it = unordered_map.find(key)"?

With the advent of C++11, we have unordered_map.cbegin/cend to specifically return us values of const_iterator. so the deduced type of 'it' in the expression "auto it = unordered_map.cbegin()" is const_iterator.
However, when it comes to unordered_map.find(key) function, I think there may be missing a "cfind()" counterpart, which returns a const_iterator specifically.
Some say that we can use "const auto it = unordered_map.find(key)" to obtain a "const iterator", but I have a strong suspicion that "const iterator" is the same "const_iterator", where "const iterator" limits the ability to change the iterator itself, while "const_iterator" limits the ability to change the content the iterator is referring to.
So, really, if we want to take advantage of "auto" type deduction fully (with the knowledge of the confusions or the variations of "auto" type deduction - auto, auto&, const auto&, etc.), how can I have unordered_map.find(key) to return a "const_iterator" without me having to explicitly specify "const_iterator" - that's after all the best use case for auto!
Below is a simple example code that demonstrates the compiler behavior:
#include "stdafx.h"
#include <unordered_map>
int _tmain(int argc, _TCHAR* argv[])
{
typedef std::unordered_map<int, int> umiit;
umiit umii;
auto it0 = umii.find(0);
it0->second = 42;
const auto it1 = umii.find(0);
it1->second = 42;
umiit::const_iterator it2 = umii.find(0);
it2->second = 42; // expected compiler error: assigning to const
return 0;
}
I'm not aware of any place that takes a const_iterator where you couldn't simply pass an iterator instead, so this deficiency may not interfere much with day-to-day code writing. However, I do prefer to use const_iterators (and const in general) wherever I don't need mutating, in the interests of general communication, so I think adding a cfind() might be a useful addition to the future standard library.
I think this code could function as a simple workaround for what you're trying to achieve, though:
template<typename T>
auto use_as_const( T const &t ) -> T const & {
return t;
}
This is a simple casting wrapper function, similar in style to move() and forward<T>(), to provide (and document) a constraint on individual usages of the object. You could then use it like this:
auto it1 = use_as_const( umii ).find(0);
This could also be used instead of leaning on cbegin() and cend(). Or, it could be used in range-based for loops:
for ( auto &element : use_as_const( some_vector_of_string ) ) {
cout << element;
// element = ""; // This line shouldn't compile.
}
In the above loop example, although I would generally prefer auto const &element : ..., I believe it would be unnecessary and element would still be deduced to be a const reference.
It's a bit of a deficiency; we have cbegin and cend but no corresponding cfind, etc.
I'd suggest using a utility function to get a const reference to the object, as per the answer to forcing use of cbegin()/cend() in range-based for:
template<typename T> constexpr const T &as_const(T &t) { return t; }
auto it1 = as_const(umii).find(0);
it1->second = 42; // fails

Length of user-defined string literal as a template argument?

Is there any way to get behavior like this?
// Some definition(s) of operator "" _my_str
// Some definition of function or macro MY_STR_LEN
using T1 = MY_STR_LEN("ape"_my_str);
// T1 is std::integral_constant<std::size_t, 3U>.
using T2 = MY_STR_LEN("aardvark"_my_str);
// T2 is std::integral_constant<std::size_t, 8U>.
It seems not, since the string literals are passed immediately to some_return_type operator "" _my_str(const char*, std::size_t); and never to a literal operator template (2.14.8/5). That size function parameter can't be used as a template argument, even though it will almost always be a constant expression.
But it seems like there ought to be some way to do this.
Update: The accepted answer, that this is not possible without an extra definition per literal, is accurate for C++11 as asked, and also C++14 and C++17. C++20 allows the exact result asked for:
#include <cstdlib>
#include <type_traits>
#include <string_view>
struct cexpr_str {
const char* ptr;
std::size_t len;
template <std::size_t Len>
constexpr cexpr_str(const char (&str)[Len]) noexcept
: ptr(str), len(Len) {}
};
// Essentially the same as
// std::literals::string_view_literals::operator""sv :
template <cexpr_str Str>
constexpr std::string_view operator "" _my_str () noexcept
{
return std::string_view(Str.ptr, Str.len);
}
#define MY_STR_LEN(sv) \
std::integral_constant<std::size_t, (sv).size()>
Reading C++11 2.14.8 carefully reveals that the "literal operator template" is only considered for numeric literals, but not for string and character literals.
However, the following approach seems to give you constexpr access to the string length (but not the pointer):
struct MyStr
{
char const * str;
unsigned int len;
constexpr MyStr(char const * p, unsigned int n) : str(p), len(n) {}
};
constexpr MyStr operator "" _xyz (char const * s, unsigned int len)
{
return MyStr(s, len);
}
constexpr auto s = "Hello"_xyz;
Test:
#include <array>
using atype = std::array<int, s.len>; // OK

Resources