2

I have a simple object with some variables. I'm storing some of these objects in a array:

class Obj {
public:
  Obj(int i, int j) : var(i), var2(j) { 
            obj.initialize(); //or something
  }
  int var, var2;
  MyOtherNonConstExprObject obj;
}
...
std::array<Obj> v{Obj{1,2}, Obj{3,4}};

Now, for optimization purpose, I want to make var constexpr. Note that I can't make my whole object/constructor constexpr since MyOtherNonConstExprObject is not known at compile time.

My end goal is to be able to do something like that at compile time (my hot path is full of those tests):

if constexpr(v[0].var == v[1].var) {
...
}

From what I understood, this implies that I need to make a template of Obj else all instances of my non-templatized classes are going to have the same value for var (which does makes sense).

So I do something like:

template<int v, int w>
class Obj {
    public:
        constexpr int var() const {
            return v;
        }
        constexpr int var2() const {
            return w;
        }
        ....
};

And access var by calling the constexpr function. This is all good, except when I try to put Objs with different template values in a same vector.

I can not do constexpr const std::array<Obj> o{Obj<1,2>{}, Obj<3,4>{}} since the 2 objects have different types.

Anyone has an idea how to declare a class member constexpr for some instances of a given class and store them in an stl container please?

Note that:

  1. I don't want to use std::any as the conversion costs seem too high (and std::variant is unrealistic on int parameter AFAIK).
  2. I don't want to use polymorphism (cost of call to v-table)

Edit: change vector to array, add second template parameter.

noneppp
  • 21
  • 2
  • 2
    Use of `constexpr` in your case yields no benefits for optimization as you create class instances at runtime on the heap. You may just use `vector` instead. Related question: [Purpose of constexpr](https://stackoverflow.com/questions/28821224/purpose-of-constexpr). – user7860670 Nov 01 '17 at 09:58
  • 1
    This has the smell of [an XY problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). *Why* do you want to do this? What is the underlying problem you want to solve by this? And have you measured, benchmarked and profiled to make sure what you think is a bottleneck actually *is*? – Some programmer dude Nov 01 '17 at 09:58
  • @VTT this is a fair point. Let's assume I'm using an std::array instead of an std::vector – noneppp Nov 01 '17 at 10:06
  • You can write `constexpr const ::std::array v{1, 2};` then. However this does not bring much of optimization benefits over non-constexpr array unless you want to perform some more constexpr computations using array items. – user7860670 Nov 01 '17 at 10:08
  • @Someprogrammerdude I want to do this to be able to do at compile time something like (`a` being my array): `if constexpr(a[0].var()==a[1].var()) {...}` since everything is known at compile time. – noneppp Nov 01 '17 at 10:08
  • @VTT sorry, i don't think this is clean. It's okay here I have only an int, but in my actual code I have a template with 3 integers. – noneppp Nov 01 '17 at 10:11
  • You can declare constructor of your class as `constexpr` so objects of this class can be used to initialize a `constexpt` array. – user7860670 Nov 01 '17 at 10:12
  • @VTT so you mean using 3 constexpr arrays outside my class Obj for storing my constexpr values? This is kind of a bummer as it breaks my object model (technically the triplet of values belong to Obj, not to the class having instances of Obj) – noneppp Nov 01 '17 at 10:19
  • No, I mean storing 3 int values inside of your class and providing constexpr constructor for your class and then storing N class instances in array. – user7860670 Nov 01 '17 at 10:20
  • But if my ints in my class are not declared constexpr, I can not access them at compile time or am i missing something? Note that not all members of my class are known at compile time. – noneppp Nov 01 '17 at 10:24
  • yes, you're missing something; objects of [literal type](http://eel.is/c++draft/basic.types#10) may be used in constant expressions ( members included ) EDIT: ah, I missed the "not all members of my class are known at compile time" this smells even more XY, can you make your requirements more precise ? – Massimiliano Janes Nov 01 '17 at 10:29
  • @MassimilianoJanes sorry for the unprecise requirements - I tried to simplify a lot my problem, probably too much. I'll edit the question. – noneppp Nov 01 '17 at 10:38
  • so, you may use a `std::tuple,Obj<2>,..>`; if the number of Obj is not know at compile time, then you'll always end up in something equivalent to either std::variant ( eg. storage+typedata+visitor) or std::any( eg. typeerasure via virtual dispatch). IMO, you should refactor your design and let compile time values emerge at the abstraction level, so that you don't need all this machinery in the first place ... – Massimiliano Janes Nov 01 '17 at 11:19
  • The issue with std::tuple is that I have to enumerate all possible types - like std::variant - when declaring the type and I wish to avoid that. I don't want to have in my code std::tuple,...,Obj<100>> . I agree that for now the best idea that came up is to make one constexpr object, but this is rather counter intuitive when looking at the application domain. Even though - it should be possible to specialize a class and store an array of specialization. – noneppp Nov 01 '17 at 11:34

0 Answers0