Want to define list of macros with same prefix - c++11

I have a bunch of macros to define with same prefix and I don't want to define them one by one.
Say, I want to define like:
static constexpr str_1 = "str_1";
static constexpr str_2 = "str_2";
....
static constexpr str_100 = "str_100";
I tried:
#define DECLARE_STR(variable_prefix, val_prefix, cur, max) do { \
if ((cur) < (max)) { \
static constexpr variable_prefix##cur = val_prefix#cur; \
DECLARE_STR(variable_prefix, val_prefix, cur+1 , max) \
} while(0)
But got errors: error: expected member name or ';' after declaration specifiers
Do I have a correct way to implement this?

There are two problems with your code.
First, the do/while(0) construct is useful to ensure that macros expand to a single statement. What you want to generate are variable definitions at the global namespace, for which statements are unsuited: just remove the do/while(0). The if won't be able to do anything about declaring variables either, it can only branch at runtime on values. But in any case...
The other issue is that you're trying to call the macro recursively. The C++ preprocessor is not able to perform such recursion: a macro cannot be expanded within its own expansion. Working around that requires a lot of boilerplate to generate iteration sequences up to a limit. Fortunately(?), Boost.Preprocessor has the boilerplate already done:
#include <boost/preprocessor/repeat.hpp>
#include <boost/preprocessor/tuple/elem.hpp>
#include <boost/preprocessor/stringize.hpp>
#define DECLARE_ONE_STR(z, n, data) \
static constexpr BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(0, data), n) = BOOST_PP_TUPLE_ELEM(1, data) BOOST_PP_STRINGIZE(n);
#define DECLARE_STR(variable_prefix, val_prefix, max) \
BOOST_PP_REPEAT(max, DECLARE_ONE_STR, (variable_prefix, val_prefix))
See it live on Coliru

Related

How to constraint the parameter package type in c++11? And How to implement the template in cpp?

For the first quesion:
I want to write a function to concatenation the strings, and it can receive multiple strings;
#include <string>
#include <vector>
#include <type_traits>
template <class... Args, typename std::enable_if<std::is_same<typename std::decay<Args...>::type, std::string>::type>::type>
std::string foo(const std::string &first, const Args &... senconds) {
std::string delimiter = "$$";
std::string ret = first;
std::vector<std::string> vec{senconds...};
for (auto second = vec.rbegin(); second != vec.rend(); second++) {
ret = delimiter + *second + delimiter + ret;
}
return ret;
}
but when I invoke it like:
std::string name = "x";
name = foo(name, "xxx");
the compiler will throw an error:
error: no matching function for call to ‘foo(std::__cxx11::string&, const char [4])’
and there will be some note:
note: couldn't deduce template parameter ‘<anonymous>’
I think I should modify the constraint in the template, and I've tried all the related methods in the type_traits, but none of them works.
For the second question:
I want to hide the implementation of some function, but for the template function, it's unable to put the definition in the .hpp, and put the implementation in the .cpp, the compiler will throw a undefined reference error. Is there any elegant way to solve this?
Thanks.
There's a bit to unwrap here.
std::decay<Args...>::type can't work. std::decay takes only a single template argument, but you attempt to expand the pack here. The expansion needs to happen on the is_same.
You are also missing a way to aggregate all the is_same predicates. Do you want to and them all or or them all? Presumably and. In C++17 that's easily done with a fold expression, but for C++11 we have to work a bit.
Finally the thing the compiler complains about: std::enable_if<bla>::type evaluates to void if bla is true. That means you're formally expecting a non-type template argument, and the compiler complains because it can't deduce which value of type void it should deduce. This is normally alleviated by forming a pointer to it instead and defaulting it to nullptr: std::enable_if<bla>::type* = nullptr.
It appears (?) that you expect foo(someString, "stringLiteral"); to work. It won't, because a string literal is not a std::string. Maybe you wanted a different predicate, but for this answer I'll stick with the original condition.
Putting all that together:
In C++17, you would write
template <class... Args,
std::enable_if_t<
(std::is_same_v<std::decay_t<Args>, std::string> && ...)
>* = nullptr
>
https://godbolt.org/z/84Dcmt
In C++11, we use this helper and add back the typename and ::type verbosity:
template <class... Args,
typename std::enable_if<
var_and<
std::is_same<typename std::decay<Args>::type, std::string>::value...
>::value
>::type* = nullptr
>
https://godbolt.org/z/2eFyX7
Base on MaxLanghof's answer, I changed the template to:
template <class... Args,
typename std::enable_if<var_and<std::is_constructible<
std::string, Args>::value...>::value>::type * = nullptr>
In this form, the function foo can be invoked like the name = foo(name, stringRed, "xxx").
Thanks #MaxLanghof again.

std::vector of type deduced from initializers before C++17 ... any workaround for C++11?

I learned that from C++17, with the deduction guides, template arguments of std::vector can be deduced e.g. from the initialization:
std::vector vec = { function_that_calculate_and_return_a_specifically_templated_type() }
However I do not have the luxury of C++17 in the machine where I want to compile and run the code now.
Is there any possible workaround for C++11? If more solutions exist, the best would be the one that keep the readability of the code.
At the moment the only idea that I have is to track the various cases along the code (luckily they should not be too many) and make some explicit typedef/using.
Any suggestion is very welcome
The usual way to use type deduction for class template when CTAD is not available is providing a make_* function template, e.g. for your case (trailing return type is necessary for C++11):
#include <vector>
#include <type_traits>
#include <tuple>
template <class ...Args>
auto make_vec(Args&&... args) ->
std::vector<typename std::decay<typename std::tuple_element<0, std::tuple<Args...>>::type>::type>
{
using First = typename std::decay<typename std::tuple_element<0, std::tuple<Args...>>::type>::type;
return std::vector<First>{std::forward<Args>(args)...};
}
You can invoke the above with
const auto v = make_vec(1, 2, 3);
which gets at least kind of close to CTAD in the sense that you don't have to explicitly specify the vector instantiation.
While the answer by lubgr is a correct way, the following template is simpler and seems to work as well:
#include <vector>
#include <string>
template <typename T>
std::vector<T> make_vec(const std::initializer_list<T> &list)
{
return std::vector<T>(list);
}
int main()
{
auto v = make_vec({1,2,3});
auto v2 = make_vec({std::string("s")});
std::string s("t");
auto v3 = make_vec({s});
return v.size() + v2.size() + v3.size();
}
One advantage of using the initializer_list template directly are more clear error messages if you pass mixed types like in make_vec({1,2,"x"});, because the construction of the invalid initializer list now happens in non-templated code.

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);
}

C++11, Is it possible to force an instance to be extern but also a constant expression of a non-type template parameter?

Using C++11, g++ (GCC) 4.4.7 20120313 (Red Hat 4.4.7-18).
Lets pretend I have a templated function (pardon my terminology if it isn't quite right).
I want to perform a "general" algorithm based on what was supposed to be compile-time instances of "field". Where the only things that really changed are these constants which I moved into trait classes (only added one here but imagine there are more). Originally I was declaring it as
constexpr field FIELD1{1};
However in C++11, non-type template params need to have external linkage (unlike C++14 which can have internal and external linkage?). So because not's in the same translation unit I needed to use extern in order to give it external linkage (sorry if I butchered that explanation also). But by defining it extern I can't define it using constexpr and it seems that losing that constexpr constructor this field is no longer a valid constant expression to qualify as a non-type template param.
Any suggestions if there is some way I can get around this? Open to a new method of doing things. Below is a simplified (incomplete, and non-compiling version to get the gist of the organization).
So the error I am seeing is along the lines of
error: the value of ‘FIELD1’ is not usable in a constant expression
note: ‘FIELD1’ was not declared ‘constexpr’
extern const field FIELD1;
Not quite sure what could be a best alternative.
I can get rid of the second error by removing the constexpr from the constructor. But then I don't know how to approach the constant expression issue.
field.H
struct field
{
int thingone;
constexpr field(int i):thingone(i){}
};
extern const field FIELD1;
field.C
#include "field.H"
const field FIELD1{0};
field_traits.H
#include "field.H"
template< const field& T >
class fieldTraits;
template< >
class fieldTraits<FIELD1>
{
public:
// Let's say I have common field names
// with different constants that I want to plug
// into the "function_name" algorithm
static constexpr size_t field_val = 1;
};
function.H
#include "field.H"
template< const field& T, typename TT = fieldTraits<T> >
void function_name()
{
// Let's pretend I'm doing something useful with that data
std::cout << T.thingone << std::endl;
std::cout << TT::field_val << std::endl;
}
So because not's in the same translation unit I needed to use extern in order to give it external linkage (sorry if I butchered that explanation also). But by defining it extern I can't define it using constexpr [...]
Per my comment, you can. It wouldn't work for you, but it's a step that helps in coming up with something that would work:
extern constexpr int i = 10;
This is perfectly valid, gives i external linkage, and makes i usable in constant expressions.
But it doesn't allow multiple definitions, so it can't work in a header file which is included in multiple translation units.
Ordinarily, the way around that is with inline:
extern inline constexpr int i = 10;
But variables cannot be declared inline in C++11.
Except... when they don't need to be declared inline because the effect has already been achieved implicitly:
struct S {
static constexpr int i = 10;
};
Now, S::i has external linkage and is usable in constant expressions!
You may not even need to define your own class for this, depending on the constant's type: consider std::integral_constant. You can write
using i = std::integral_constant<int, 10>;
and now i::value will do exactly what you want.

Why constexpr is not evaluated at compile time (MSVC 2015)?

recently I've tried to take advantage of C++0x constexpr under MSVC 2015 and my objective was to achieve compile-time hash strings. I wrote a simple FNV-1a hash algorithm as a constexpr function using, as required, a single return statement (ternary operator) and calling only constexpr functions, here it is:
template <size_t N>
constexpr U32 StringID_FNV1a_32(const char(&str)[N], I32 charIndex = 0, U32 hash = 2166136261U)
{
return charIndex < N-1 ? StringID_FNV1a_32(str, charIndex +1, (hash ^ str[charIndex]) * 16777619U) : hash;
}
I also made a little macro to be able to change the algorithm under the hood without any trouble:
#define STRING_ID(str) core::utility::StringID_FNV1a_32(str)
then I used this macro in my code, carefully checking if any breakpoint was hit and, also, the generated assembly code. Here's the little scenario:
//1. normal variable test
U32 hash1 = STRING_ID("abc");
//2. enum test
enum {
hash2 = STRING_ID("abc")
};
//3. constexpr variable test
constexpr U32 hash3 = STRING_ID("abc");
And here the facts:
first test was called at run time
second test was performed at compile time
third test was called at run time
As you can imagine I'm a little confused about the first and the third attempt.
Why in the third scenario is the compiler allowed to call the function at runtime? even though the msdn says clearly "The primary difference between const and constexpr variables is that the initialization of a const variable can be deferred until run time whereas a constexpr variable must be initialized at compile time." [https://msdn.microsoft.com/it-it/library/dn956974.aspx#Anchor_3]
Can be related to the fact that I'm in debug mode with all the optimizations turned off? and what about the first test?, is there any way to force the compiler to perform the hash at compile time?
MSVC's behavior can be quite strange, however it is possible to force it to make constexpr functions run at compile time.
#define COMPILE_TIME(value) ((decltype(value))CompileTime<decltype(value), value>::ValueHolder::VALUE)
template<typename T, T Value>
struct CompileTime
{
enum class ValueHolder : T
{
VALUE = Value
};
};
This forces the value to be passed as a template argument + an enumeration value, thus making it strictly compile-time only. Also please note that this works only for integer types.
You can use it simply by putting the call to the constexpr function as a parameter to the COMPILE_TIME macro:
constexpr U32 hash = COMPILE_TIME(STRING_ID("abc"));

Resources