7

I have a function:

void foo(int n) {
    std::cout << "foo(int)\n";
}

which can be called using different arguments, it can be char, double, float etc.:

foo(123); // 1
foo('c'); // 2
foo(0.2); // 3
foo(0.2f); // 4
// ...

... but I would like to allow only int arguments (literal or variable), so that 2,3,4,... above would be illegal. My current solution is to delete those overloads with:

void foo(char) = delete;
void foo(float) = delete;
void foo(double) = delete;

but this list of overloads can be really long, and always someone can write a class which will implicitly convert to int what will allow to use my int only function in wrong way, so I found that writing (instead of long explicit list):

template<typename T>
void foo(T) = delete;

works as expected.

Is there any downside to using template as above? or maybe there are some better ways to aprach this problem?

mike
  • 1,670
  • 11
  • 21
  • 1
    What is _wrong_ with non-(truly)`int` parameters? If the values are beyond your function's range, you'd better `throw` exceptions. – edmz Jan 11 '17 at 12:09
  • 1
    @AlgirdasPreidžius The only difference is, this question is basically asking for potential downsides to the answer given in that question. – BoBTFish Jan 11 '17 at 12:10
  • Even if this question is well-written, it doesn't show any research attempt, since searching for the exact title, shows several questions about the same issue. – Algirdas Preidžius Jan 11 '17 at 12:11
  • 1
    I've done the same thing already in real production code. Shorts will not be implicitly converted to int either, though; it is kinda what you want. – JVApen Jan 11 '17 at 12:11
  • I don't see any downsides. The compiler will favour `foo(int)` over any template version when `int` is used (non-template function preference), and use the deleted template function for all other types. – Karl Nicoll Jan 11 '17 at 12:12
  • @BoBTFish: There is more than one answer given in that question. – Lightness Races in Orbit Jan 11 '17 at 12:13
  • 1
    One downside is, that it disallows calling `foo` with `std::reference_wrapper` (i.e. `foo(std::ref(i))`), but that probably does not matter for PODs. – Zereges Jan 11 '17 at 12:14

1 Answers1

2

You can use static_assert with std::is_same:

template<typename T>
void foo(T i) {
  static_assert(std::is_same<T, int>::value, "Not int");
  std::cout << "foo(int)\n";
}
fandyushin
  • 2,350
  • 2
  • 20
  • 32