Reputation: 9003
I have a class C
and want to do the following:
class C {
public:
C(const size_t aa, const size_t bb) { // aa and bb are compile time constants
// when aa + bb > 10 raise a compile time error
}
private:
size_t a;
size_t b;
}
Constructor C::C
should type check and reject any aa
and bb
values that are not known at compile-time and are not positive integers. If that check passes, the compiler should check their sum. If the sum is greater than 10, the compiler should reject the constructor call.
Is this doable (and how) using only ISO C++11, not relying on the specific compiler?
Upvotes: 3
Views: 373
Reputation: 217085
Parameter values are not constexpr, so cannot be used in constant expression, but types can:
class C {
public:
template <std::size_t N1, std::size_t N2>
constexpr C(std::integral_constant<size_t, N1>,
std::integral_constant<size_t, N2>) : a(N1), b(N2)
{
static_assert(N1 + N2 <= 10);
}
private:
size_t a;
size_t b;
};
With usage
C c_KO{std::integral_constant<std::size_t, 40>{}, std::integral_constant<std::size_t, 2>{}}; // KO
C c_OK{std::integral_constant<std::size_t, 4>{}, std::integral_constant<std::size_t, 2>{}}; // OK
UDL might allow to reduce verbosity:
template <char ... Digits>
constexpr std::size_t compute_value()
{
std::size_t res = 0;
for (auto digit : {Digits...}) {
if (digit < '0' || '9' < digit) throw std::domain_error("Invalid number");
res *= 10;
res += digit - '0';
}
return res;
}
template <char ... Digits>
constexpr std::integral_constant<std::size_t, compute_value<Digits...>()>
operator "" _c() { return {}; }
With usage
C c_KO{40_c, 2_c}; // KO
C c_OK{4_c, 2_c}; // OK
Upvotes: 1
Reputation: 595432
At compile-time, what you are asking for is possible only with templates, eg:
template<size_t aa, size_t bb>
class C {
public:
C() {
static_assert(aa > 0, "aa must be > 0");
static_assert(bb > 0, "bb must be > 0");
static_assert((aa + bb) <= 10, "aa + bb must be <= 10");
}
};
C<1, 2> c1; // OK
C<5, 6> c2; // compile error
Otherwise, at run-time, all you can do is throw an exception on bad input, eg:
#include <stdexcept>
class C {
public:
C(const size_t aa, const size_t bb) : a(aa), b(bb) {
if (aa == 0)
throw std::runtime_error("aa must be > 0");
if (bb == 0)
throw std::runtime_error("bb must be > 0");
if ((aa + bb) > 10) {
throw std::runtime_error("aa + bb must be <= 10");
}
}
private:
size_t a;
size_t b;
};
C c1(1, 2); // OK
C c2(5, 6); // runtime error
Upvotes: 3