Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Template specialization for class wrappers

Tags:

c++

c++17

c++20

I can't have my int class wrapper acting like a primitive int in template specialization.

I've prepared this code to explain my issue in detail:

#include <iostream>
#include <stdlib.h> 

class Integer
{
  int _v;
public:
  constexpr explicit Integer(int v) : _v(v) {}
  constexpr Integer next() const { return Integer(_v + 1); }
  constexpr operator int() const { return _v;}
};

static constexpr auto integer1 = Integer(1);
static constexpr auto integer2a = Integer(2);
static constexpr auto integer2b = integer1.next();

template <const Integer& i>
void foo_Integer()
{
  static auto foo_id = rand();
  std::cout << foo_id << std::endl;
}

static constexpr auto int1 = 1;
static constexpr auto int2a = 2;
static constexpr auto int2b = int1 + 1;

template <int i>
void foo_int()
{
  static auto foo_id = rand();
  std::cout << foo_id << std::endl;
}

int main()
{
  foo_int<int1>();
  foo_int<int2a>();
  foo_int<int2b>(); // same template specialization as above -> :)

  foo_Integer<integer1>();
  foo_Integer<integer2a>();
  foo_Integer<integer2b>(); // different template specialization -> :(
}

As you can see running the code

foo_int<int2a>();
foo_int<int2b>();

use the same template specialization, while

foo_Integer<integer2a>();
foo_Integer<integer2b>();

use different template specializations.

This is, of course, correct, from the compiler point of view, since the template accepts a const Integer&, but I hope there are other better approaches to workaround the issue.

like image 594
c.bear Avatar asked Mar 11 '26 10:03

c.bear


1 Answers

You can easily make Integer a structural type (C++20). Then its values are valid template parameters.

class Integer
{
public:
  int _v;

  constexpr explicit Integer(int v) : _v(v) {}
  constexpr Integer next() const { return Integer(_v + 1); }
  constexpr operator int() const { return _v;}
};

template <Integer i>
void foo_Integer()
{
  static auto foo_id = rand();
  std::cout << foo_id << std::endl;
}

Live

And the values would be equivalent, even if they come from objects with different identities.

like image 63
StoryTeller - Unslander Monica Avatar answered Mar 15 '26 20:03

StoryTeller - Unslander Monica



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!