Inline constexpr and anonymous namespace variables? - c++

I have the following problem. In a .hpp file I have a function Space::foo() that must use a namespace global variable, I thought of hiding it in an anonymous namespace. But now I wonder, do I risk having values defined in each translation unit with multiple copies or there will only be one? Thanks for helping. This comes from the fact that I needed a bunch of functions in the Space namespace with a sort of private data part (the anonymous namespace stuff) so that Space is sort of like a class with only static members, but I don't want to have multiple copies of these variables if I include the .hpp file in different units.
// .hpp file
#include <array>
namespace Space {
namespace {
constexpr std::array<int, 10000> fill() { /* ... */ };
inline constexpr std::array<int, 10000> values = fill();
}
inline int foo(int i) {
return values[i];
}
}

do I risk having values defined in each translation unit with multiple copies
Yes. You'll have one definition of values in each TU. You can't declare it extern constexpr either because [dcl.constexpr]/1 says "The constexpr specifier shall be applied only to the definition of a variable".
Since the purpose seems to be to be able to pick values that are constant evaluated you could possibly make both fill and foo consteval and skip <anonymous>::values.
namespace Space {
namespace {
consteval std::array<int, 10000> fill() {
return {}; // replace with your filling algorithm
};
}
inline consteval int foo(size_t i) {
return fill()[i];
}
inline consteval int bar(size_t i, size_t j) {
constexpr auto values = fill();
return values[i] + values[j];
}
}
This would make it possible for foo and any other consteval function to use the algorithm in fill() and to use the result in constexpr/consteval situations.
constexpr auto x = Space::bar(10, 20);

Related

Parametric function in namespaces (C++)

I need to define 3 functions that have the same goal, but whose behaviours changes slightly based on 3 sets of constant values; in other words, i could simply write a function that does that in all 3 cases by taking those values as inputs. But since there really many constants (and only 3 different sets of those) i'd definitely avoid such a long function declaration. Furthermore, i'll need those sets of constants in other files for related computations.
I was thinking about using namespaces, but i couldn't find anything that suited what i wanted to achieve. Just to make things more comprehensible, here is an example of what i'd desire (but obviously doesn't compile):
int parametric_function() {
return a_constant + 1; //'a_constant' isn't defined yet
}
namespace first_behaviour {
const int a_constant = 10;
//make the function use the variable 'a_constant' defined here in some way
int (*f)() = parametric_function;
}
namespace second_behaviour {
const int a_constant = 20;
//make the function use the variable 'a_constant' defined here in some way
int (*f)() = parametric_function;
}
As you can see, i'd only need to write my parametric function once, and i can use the namespace to get the right function and the associated set of constants. Do you have any suggestions on what i could try doing?
If you have only one variable, you can pass it directly as a template parameter, as suggested in this answer.
But if you have more than one, you can wrap them in a struct:
#include <iostream>
struct FirstBehavior
{
static constexpr int a_constant = 10;
};
struct SecondBehavior
{
static constexpr int a_constant = 10;
};
template <typename T>
int ParametricFunction()
{
return T::a_constant + 1;
}
int main()
{
std::cout << ParametricFunction<FirstBehavior>() << '\n'; // 1
}
In c++ you have templates:
template <int a_constant>
int parametric_function() {
return a_constant + 1;
}
namespace first_behaviour {
auto f = parametric_function<10>;
}
Using HolyBlackCat's suggestion of a struct and a template, here would be one approach.
The struct is just a wrapper to hold the variable. In this example, I made it a stateful variable (non-const), static to the struct wrapper. It has the requirement to be the expected name by the parameteric_function.
I thought making the example use a non-const variable might be more generally applicable for other types, such as std::string or std::vector or whatever you may need.
The extern int (*f)(); was just to squelch a compiler warning.
#include <iostream>
using std::cout;
template <typename T>
int parametric_function() {
++T::a_variable;
return T::a_variable;
}
namespace first_behaviour {
struct VarHolder {
static inline int a_variable = 10;
};
extern int (*f)();
int (*f)() = &parametric_function<VarHolder>;
} // first_behaviour
namespace second_behaviour {
struct OtherVarHolder {
static inline int a_variable = 20;
};
extern int (*f)();
int (*f)() = &parametric_function<OtherVarHolder>;
} // second_behaviour
int main() {
int x = first_behaviour::f();
int y = second_behaviour::f();
cout << x << " " << y << "\n";
}
Possibly you could do with templates. You could:
template <int CONST_VAL>
int par_func();
template<>
int par_func<10>(){ return 4; }
template<>
int par_func<20>(){ return 1; }
template<>
int par_func<30>(){ return 9; }
You could then alias these names to some other function if you want, or you can leave them like this. This also ensures that only the specialisations can be used.
You can also do your example like:
template <int CONST_VAL>
int par_func(){
return CONST_VAL + 1;
}
You can then put this in an implementation file and explicilty instantiate only the ones you use, like:
template int par_func<10>();
You can use this the same way with your namespace model like:
namespace func1 {
int(* func)() = &par_func<10>;
}
namespace func2 {
int(* func)() = &par_func<20>;
}

Idiom for a C++11 enum with methods and static instances?

I'd like to do the following (which won't compile):
class Foo {
int value;
Foo(const int arg)
: value{arg}
{}
public:
static const Foo a{0};
static const Foo b{1};
static const Foo c{2};
Foo func(const Foo& foo) {...}
};
so that the the instances of Foo are strongly controlled (like in an enum) and so that I can write code like auto foo = Foo::a; and auto foo = Foo::a.func(Foo::b);
Unfortunately, the code won't compile under C++11 because the static instances have incomplete type.
Is there an idiom for this?
You can do it quite easily but you need to put the definitions of your constants outside the class:
class Foo {
int value;
// In C++17, you could make this constexpr.
Foo(const int arg)
: value{arg}
{}
public:
// in C++20, you could make these constinit.
static const Foo a;
static const Foo b;
static const Foo c;
};
// In C++11 these need to go in the source file to avoid linker errors.
// In C++17 you could make them inline and put them in the header.
// In C++20 you could make them constinit.
const Foo Foo::a = 0;
const Foo Foo::b = 1;
const Foo Foo::c = 2;
I wouldn't call this an elegant solution though. Particularly in C++11, these constants can't be inlined by the compiler because they need to go into the source file. This can have a significant impact on performance. So if you're going to do it, I would recommend using at least C++17, if not C++20.
Generally, C++ enums are meant to be integer constants and there is no support for getting the ordinal or name of an enum like there is in Java. An alternative approach is to use an enum class with no values (which defaults to values 0, 1, 2, ...) and then use them as indices inside of lookup tables.
Using a switch for properties can also do the trick:
enum class Axis : unsigned { X, Y, Z };
// in C++17, you could make this constexpr.
inline const char *nameOf(Axis axis)
{
switch (axis) {
case Axis::X: return "X";
case Axis::Y: return "Y";
case Axis::Z: return "Z";
}
}

Variable length array error with constexpr

I have a class with a member function which declares an array whose size is based off a formula.
template <int SIZE>
class Example{
constexpr int lookup(const int n) const
{
return n * n + n;
}
inline void func()
{
double array[lookup(SIZE)];
}
};
This gives me the vla error. I think it should work because SIZE is resolved at compile time, and lookup is a constexpr. I know the following will work:
template <int SIZE>
class Example{
inline void func()
{
constexpr int sz = SIZE * SIZE + SIZE;
double array[sz];
}
};
I guess I'm just trying to figure out why
EDIT Sorry for the typos, was trying to just write a smaller example and ended up with the missing n and class name.
It's complicated...
First of all, some compilers (see MikeCAT answer and Bill Lynch linked example) can compile the following code (if you give a name to the class and correct lookup() naming n the argument)
inline void func()
{
double array[lookup(SIZE)];
}
because they support a C99 extension that accept the "variable length array" feature.
But this extension isn't standard C++.
You can verify this modifying func() as follows (almost equivalent, in standard C++)
inline void func()
{
constexpr int s = lookup(SIZE);
double array[s];
}
and this can't compile if lookup() is a non-static method
Consider that
lookup(SIZE);
is a short form for
this->lookup(SIZE);
I mean... the use of lookup() involve an object of your class.
The problem is that your func() method is available for both constexpr and non-constexpr objects.
Suppose you have a non-constexpr object: calling func() from it you impose that
constexpr int s = this->lookup(SIZE);
is evaluated compile-time.
That is: you impose that the this pointer (so the object itself) is available compile-time.
This is clearly impossible for run-time created objects, so your code can't compile.
Different if you declare lookup() as a static method: this way, calling lookup() doesn't involve an object of your class so your code can compile.
Class template must have a name.
n is not declared in lookup.
This should work as C++11:
template <int SIZE>
class hoge { // add hoge
constexpr int lookup(const int n) const // add n
{
return n * n + n;
}
inline void func()
{
double array[lookup(SIZE)];
}
};

Enum like calculated constants

Actually this "problem" feels extremely simple. While doing some calculated icon offsets, I came up with the following approach:
namespace Icons {
struct IconSet {
constexpr IconSet(size_t base_offset) noexcept
: base_offset_(base_offset), icon(base_offset * 3), iconSmall(icon + 1), iconBig(icon + 2) {
}
size_t icon;
size_t iconSmall;
size_t iconBig;
size_t base_offset_;
constexpr size_t next() const {
return base_offset_ + 1;
}
};
static constexpr IconSet flower = IconSet(0);
static constexpr IconSet tree = IconSet(flower.next());
static constexpr IconSet forest = IconSet(tree.next());
static constexpr IconSet mountain = IconSet(forest.next());
}
Now one may write Icons::tree.iconBig for example to get that icon's calculated offset. Basically the designer can change the icons - sometimes adding/removing as well - but always has to provide the entire set (normal, small and big) by convention.
As you see, the issue with this approach is that I had to do that next() function and use it repeatedly - a normal enum wouldn't have this downside.
I know of BOOST_PP and other macro tricks, but I was hoping for something without macro's - since I have a feeling it is not needed and I then sort of would prefer what I already have with the plain next() function.
Another solution would of course just be a normal enum and a calculation function, but that is defeating the purpose of laying it out precalculated.
Hence, I am looking for a simple and portable solution that will give that enum-like functionality. It doesn't have to be compile time or constexpr if for example just inline will make it easier.
Here is an approach you can use, based on a fold expression over a compile time integer sequence to instantiate the icons by index. The structured binding gets you individually named non-static, non-constexpr variables.
The anonymous namespace inside Icons makes those definitions visible in this translation unit only, which you may or may not want.
Compiler explorer link so you can explore the code options yourself.
#include <cstddef>
#include <array>
#include <utility>
namespace Icons {
struct IconSet {
constexpr IconSet(size_t base_offset) noexcept
: base_offset_(base_offset), icon(base_offset * 3), iconSmall(icon + 1), iconBig(icon + 2) {
}
size_t icon;
size_t iconSmall;
size_t iconBig;
size_t base_offset_;
};
template <std::size_t... Ints>
constexpr auto make_icons_helper(std::index_sequence<Ints...>) -> std::array<IconSet, sizeof...(Ints)>
{
return {IconSet(Ints)...};
}
template <size_t N>
constexpr auto make_icons()
{
return make_icons_helper(std::make_index_sequence<N>{});
}
namespace {
auto [flower, tree, forest, mountain] = make_icons<4>();
}
}
int main()
{
return Icons::forest.iconSmall;
}
A simple, non-constexpr solution using a static counter and relying on the fact that static initialization is performed top-to-bottom within a single TU:
namespace Icons {
namespace detail_iconSet {
static std::size_t current_base_offset = 0;
}
struct IconSet {
IconSet() noexcept
: base_offset_(detail_iconSet::current_base_offset++)
, icon(base_offset_ * 3)
, iconSmall(icon + 1)
, iconBig(icon + 2) { }
std::size_t base_offset_;
std::size_t icon;
std::size_t iconSmall;
std::size_t iconBig;
};
static IconSet flower;
static IconSet tree;
static IconSet forest;
static IconSet mountain;
}
See it live on Coliru
The catch is that this will behave weirdly if you have several headers containing IconSet definitions (i.e. their numbering will change depending on the order of inclusion), but then I don't think there's a way to avoid that.

in-class initialization of non-integral static data

So I just learned via a compiler error that in-class initialization of arrays is invalid (why?). Now I would like to have some arrays initialized in a template class, and unfortunatly the contents depend on the template parameter. A condensed testcase looks like this:
template<typename T>
struct A {
T x;
static const int len = sizeof(T); // this is of course fine
static const int table[4] = { 0, len, 2*len, 3*len }; //this not
}
Any idea how to pull out the constant array?
EDIT: Added the 'int's.
Just as you'd do it without templates; put the initialization outside the class' declaration:
template<class T>
const int A<T>::table[4] = { 0, len, 2*len, 3*len };
class Y
{
const int c3 = 7; // error: not static
static int c4 = 7; // error: not const static const
float c5 = 7; // error not integral
};
So why do these inconvenient restrictions exist? A class is typically declared in a header file and a header file is typically included into many translation units. However, to avoid complicated linker rules, C++ requires that every object has a unique definition. That rule would be broken if C++ allowed in-class definition of entities that needed to be stored in memory as objects.
for more detail read : How do I define an in-class constant?
template <typename T, int index>
struct Table {
static const len = sizeof(T);
static const value = len*index;
};