8

What I mean is this, I have a function in c++ where I want to deposit money into an account. This function should be able to accept floats, doubles, integers, etc. as these are all valid forms of an input, as all I need is a number to deposit.

Thus, I declared:

template <typename type> void Deposit(type t) {...} 

Now the only issue I have is this: theoretically, a user of this class down the road could pass a char or string to this function and have unintended consequences of doing so. How would I go about restricting type to integers, floats, doubles and shorts? Is it possible to restrict this within the function definition so that others, when programming with this function get a compiler/linker error rather than having to use try{...} catch(...){...}?

12
  • 2
    What are you doing inside the function that you think will compile properly regardless of what type t is? Commented Jun 30, 2017 at 13:46
  • 3
    Please do not use floating point numbers for money. Makes it impossible to balance the books. Customers get uppity over the pennies Commented Jun 30, 2017 at 13:46
  • 1
    You surely mean typename instead of typedef, right? Commented Jun 30, 2017 at 13:47
  • 2
    A char is a numerical type in C++ (and also what many compilers use for typedef int8_t) Commented Jun 30, 2017 at 13:48
  • 2
    You do not need decimals. Use int as pennies. Then present that as appropriate. Avoiding floating point numbers remove the possibility of rounding errors creeping in Commented Jun 30, 2017 at 14:39

2 Answers 2

18

What you need std::is_arithmetic to constrain the template type to a arithmetic types (integral or floating point). You can use it like

template <typename T, typename std::enable_if<std::is_arithmetic<T>::value>::type* = nullptr> void Deposit(T t) {...} 
Sign up to request clarification or add additional context in comments.

4 Comments

Note that std::is_arithmetic is true also for bool, that isn't one of the types listed in the question.
This works for my (slightly different) case. I mostly understand how this works except for the "::type* = nullptr>" bit. Can somebody explain me that part?
@MaestroMaus std::enable_if has a member called type if the condition is true. What I am doing is saying that if the condition is true then the template has a non type template parameter of type type* (which is void* since the default type for enable_if is void) and it's value is nullptr. if the condition is false, the substitution fails, and the entire template is silently (no compiler error) discarded from the overload set.
Documentation: en.cppreference.com/w/cpp/types/enable_if. Note that you can also use a static_assert to do essentially the same thing inside the class or function being defined. Here's the pattern to follow: Use static_assert to check types passed to macro.
5

I am afraid you are getting wrong approach, you should create a class that properly work with money (including necessary operations for your domain - adding, subtracting etc), test it, add methods to print it and/or convert to string, and make your function accept only that type:

class Money { ... }; void Deposit( Money amount ); 

So by adding constructors you can control which types can be accepted:

class Money { public: explicit Money( double v ); explicit Money( int64_t cents ); Money( int64_t cents ); ... }; 

this way you can control what conversions can be done, and it would be done not only for this particular function but whole class. Otherwise you will need to re-implement the same logic in many functions (I doubt your system only would need functionality to deposit).

1 Comment

There is no need to store the dollars and cents separately. You can just say __int64 cents. Dollars are cents / 100. that's how must currency calculations work, using fixed point arithmetic.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.