4

I am writing a class template that is parametrized on size_t,

template<size_t k>
class MyClass {...}

The parameter k should really be less than 10, in this case and I would like it to fail to compile if it goes beyond that. How can I do that in C++11 and above?

MyClass<1> instance1; // ok
MyClass<2> instance2; // ok
MyClass<100> instance100; // fail to compile
dhu
  • 718
  • 6
  • 19

3 Answers3

12

Use static_assert

template<size_t k>
class MyClass {
    static_assert(k < 10, "Illegal k");
};

int main() {
  MyClass<50> t; //< Compile time failure
}
cplusplusrat
  • 1,435
  • 12
  • 27
  • You can put `static_assert` into the class body as well. With your way only the ctor calls will fail to compile which may or may not be what OP wants. – sebrockm Aug 30 '18 at 22:00
  • Updated. The solution. Yes, you are right, I can put the `static_assert` anywhere in the class. – cplusplusrat Aug 30 '18 at 22:02
  • 3
    I voted for this answer. While I find SFINAE (e.g. `std::enable_if`) very funny to use, it is less readable and the compile-time error is not as clear as what you can get with `static_assert`. – vdavid Aug 30 '18 at 22:05
5

You could add a check in the template parameter like

template<size_t k, std::enable_if_t<k <= 10, bool> = true>
class MyClass {};

This will allow MyClass<1> instance1; but MyClass<100> instance100; will fail to compile.

NathanOliver
  • 171,901
  • 28
  • 288
  • 402
  • I'm very curious why anyone would use this technique; it seems to me that cplusplusrat's `static_assert()` technique is much more straightforward and understandable than this technique. Also I'm not familiar with `std::enable_if_t<>`, can you add an explanation of how this accomplishes what the OP needs? What about it makes `MyClass<100>` fail to compile? – phonetagger Aug 30 '18 at 22:23
  • @phonetagger If you're doing some more complex meta programming, `enable_if` gives you way more opportunities. E.g. it is common to enable certain function overloads for some template parameters and some other overloads for others. But in this particular use case I see no reason to prefer it over `static_assert`, as you say. – sebrockm Aug 30 '18 at 22:57
  • @L.F. I've updated the answer to use a `bool`. I've been working through answer but missed this one. – NathanOliver Jul 19 '19 at 12:20
  • @NathanOliver Never mind, this is being neglected all the time and no compiler actually diagnoses this at all. – L. F. Jul 19 '19 at 12:54
  • 1
    @L.F. No, they don't. I've heard from some people some compilers will error, but the major ones don't and I guess that is a good thing as there are so many resources that do it the `void*` way. FWIW all of my new code I use `enable_if_t<..., boo> = true` to compliance proof the code. Won't matter for much longer but I like seeing the `true` as it reminds me this is only enabled when the condition is true. – NathanOliver Jul 19 '19 at 12:56
  • @NathanOliver Wow, really. I was testing only GCC and Clang and claimed that nobody diagnoses that ... I guess I am gonna update my https://stackoverflow.com/q/56003162, but later ... – L. F. Jul 19 '19 at 13:00
1

You can use std::enable_if if you are using C++11.

template<std::size_t k, typename unused = typename std::enable_if<k <= 10>::type>
class MyClass {};

You can use std::enable_if_t if you are able to use C++14 or higher.

template<std::size_t k, typename unused = std::enable_if_t<k <= 10 >>
class MyClass {};
R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • I'm very curious why anyone would use these techniques; it seems to me that cplusplusrat's `static_assert()` technique is much more straightforward and understandable than either of these techniques. Also I'm not familiar with `std::enable_if<>` or `std::enable_if_t<>`, can you add an explanation of how these accomplish what the OP needs? – phonetagger Aug 30 '18 at 22:20
  • You'll have to lookup SFINAE in C++. Here's a starting page: https://en.cppreference.com/w/cpp/language/sfinae. – R Sahu Aug 30 '18 at 22:23
  • Figuring out how SFINAE and `std::enable_if<>` or `std::enable_if_t<>` work is hard enough; it would still be helpful to add a couple sentences explaining the essence of how that accomplishes what the OP needs, even if you leave out the details. Scott Meyers would never have sold more than a few books if he didn't write in a way that was understandable to his readers. SO is not supposed to be a technical reference site for people who are already language experts; it's supposed to be more helpful than that. – phonetagger Aug 30 '18 at 22:48
  • @phonetagger Unfortunately, SFINAE is generally considered a very basic part of C++ that is expected to be covered in primers. – L. F. Jul 19 '19 at 05:13
  • Also, an (over) intelligent user can hijack this solution by explicitly providing a second argument. – L. F. Jul 19 '19 at 12:54