Let's say I have a class that simply performs an addition for any type T. I want to add an additional range check (based on a template parameter of type bool) that will check whether the result of the addition belongs to the given range, otherwise it will throw. One way to do this is to wrap all the basics of a class in a base class and then specialize in the boolean template parameter. Sort of:
template<typename T>
class DummyImpl
{
private:
T mval, mmax;
public:
constexpr explicit DummyImpl(T x, T max_x) noexcept
: mval{x}, mmax{max_x}
{};
virtual ~DummyImpl() {};
T max() const noexcept {return mmax;}
T val() const noexcept {return mval;}
};
template<typename T, bool B>
class Dummy : DummyImpl<T> {};
template<typename T>
class Dummy<T, true> : DummyImpl<T>
{
public:
explicit Dummy(T x, T max_x) noexcept : DummyImpl<T>(x, max_x) {};
T add(T x) const noexcept( !true )
{
T ret_val = x + DummyImpl<T>::val();
if (ret_val < 0 || ret_val > DummyImpl<T>::max()) {
throw 1;
}
return ret_val;
}
};
template<typename T>
class Dummy<T, false> : DummyImpl<T>
{
public:
explicit Dummy(T x, T max_x) noexcept : DummyImpl<T>(x, max_x) {};
T add(T x) const noexcept( !false )
{
return x + DummyImpl<T>::val();
}
};
Now the user can write code, for example:
int main()
{
Dummy<float,false> d(0, 1000);
std::cout <<"\nAdding 156.7 gives " << d.add(156.7);
std::cout <<"\nAdding 3156.7 gives " << d.add(3156.7);
std::cout <<"\n";
return 0;
}
Is there a way to do this without using inheritance? I would suggest that using a nested class would be more efficient, but the following code does not compile.
template<typename T, bool RC>
class Dummy
{
private:
T mval, mmax;
template<bool I, typename S> struct add_impl {};
template<typename S> struct add_impl<true, S>
{
T operator()(T x) const noexcept( !true )
{
T ret_val = x + mval;
if (ret_val < 0 || ret_val > mmax) {throw 1;}
return ret_val;
}
};
template<typename S> struct add_impl<false, S>
{
T operator()(T x) const noexcept( !false )
{
return x + mval_ref;
}
};
public:
constexpr explicit Dummy(T x, T max_x) noexcept
: mval{x}, mmax{max_x}
{};
void bar() const { std::cout << "\nin Base."; }
T max() const noexcept {return mmax;}
T val() const noexcept {return mval;}
T add(T x) const noexcept( !RC )
{
return add_impl<RC, T>()(x);
}
};
int main()
{
Dummy<float,false> d(0, 1000);
std::cout <<"\nAdding 156.7 gives " << d.add(156.7);
std::cout <<"\nAdding 3156.7 gives " << d.add(3156.7);
std::cout <<"\n";
return 0;
}
Error with error message (in g ++):
error: invalid use of non-static data member ‘Dummy<float, false>::mval’
? , , ? Dummy? /?