ckormanyos/wide-integer

Cannot use integers in template parameters due to private data members.

xamidi opened this issue · 6 comments

According to README.md:

  • Signed and unsigned versions of uintwide_t should behave as closely as possible to the behaviors of signed and unsigned versions of built-in int.

So I tried to use math::wide_integer::uint256_t as a template parameter, but it failed with an error

'math::wide_integer::uintwide_t<256, unsigned int>' is not a valid type for a template non-type parameter because it is not structural

Fix:

This seems to be caused by the existence of non-public data members.
In math/wide_integer/uintwide_t.h I replaced all private: by public:, and now it works.

Code example:

#include <cstdint>
#include <iostream>
#include "wide-integer/uintwide_t.h"
template<typename UInt, uint32_t B = 8 * sizeof(UInt), UInt MAX = -UInt(1)> void f(uint32_t n) {
	std::cout << B << "-bit ; MAX = " << MAX << ", n = " << UInt(n) << std::endl;
}
int main() {
	f<math::wide_integer::uint256_t>(42); // prints "256-bit ; MAX = 115792089237316195423570985008687907853269984665640564039457584007913129639935, n = 42"
}

Apart from that, great work! sizeof(UInt) and -UInt(1) wouldn't even work with the types of Boost.Multiprecision, and UInt(-1) refused to be constexpr. All these things work fine with uintwide_t.

... tried to use math::wide_integer::uint256_t as a template parameter, but it failed with an error ...

... the existence of non-public data members

Thank you for your query. I must admit, I have never tried this exact kind of templatization. Please allow me to take a look at a few options regarding compatibility and get back to your query shortly.

I would not immediately want to make the private data members public, but we might consider doing this with a new, specific compiler switch.

Anyway, please allow me to investigate your query a bit. i'll get back with suggestions...

Kind regards, Chris

Proposed solution:

#define WIDE_INTEGER_DISABLE_PRIVATE_CLASS_DATA_MEMBERS

This optional macro can be used to disable uintwide_t's private data members and make them public. This allows the uintwide_t class to be used as a structured class object, such as is needed for constant-valued template parameters in the sense of C++20's constexpr-ness.

Making private data members public is unusual for some designs so the default value is WIDE_INTEGER_DISABLE_PRIVATE_CLASS_DATA_MEMBERS disabled and uintwide_t's data members remain private.

The repair is cycling in CI.

Cc: @xamidi

Hello @xamidi this is now fixed by #336, see change set b3f4aac

Please use either the command line switch when callinng the compiler:

-DWIDE_INTEGER_DISABLE_PRIVATE_CLASS_DATA_MEMBERS

or

#define WIDE_INTEGER_DISABLE_PRIVATE_CLASS_DATA_MEMBERS

above the inclusion of the uintwide_t.h header file.

Thank you for the quick fix. I switched to the original file already, and all seems good. :)

Thank you for the quick fix. I switched to the original file already, and all seems good.

Great! Thank you @xamidi for raising this interesting issue. Glad it works.
If you encounter anything else or have future ideas, please feel free to stop by.