WhatABeautifulWorld
WhatABeautifulWorld

Reputation: 3388

How to constrain class templates and data members with std::enable_if

I have a class template:

template<int a, int b>
class foo {
};

I only want to instantiate it when a + b == 10. Could I make this possible using std::enable_if?

Furthermore, if I have a data member in class foo:

template<int a, int b>
class foo {
    int c;
};

I only want to have c when a == 5.

How do I do that using std::enable_if? Is this one the correct case to use std::enable_if?

Upvotes: 3

Views: 3611

Answers (4)

Amir Kirsh
Amir Kirsh

Reputation: 13752

With C++20

You can achieve that simply by adding requires to the template:

template<int a, int b> requires (a + b == 10)
struct foo {
    int c;
};

int main() {
    foo<3, 7> ok;
    // foo<3, 8> doesnt_compile;
}

The requires clause gets a constant expression that evaluates to true or false deciding thus whether to consider this as a proper match, if the requires clause is true, or ignore it otherwise.

Code: https://godbolt.org/z/yHh4Et

Upvotes: 5

Jonathan Wakely
Jonathan Wakely

Reputation: 171263

Simple, just don't use enable_if

template<bool Ten>
struct Base
{
    int c;
};

template<>
struct Base<false>
{ };

template<int a, int b>
struct foo : Base<a+b == 10>
{
};

Upvotes: 3

user142019
user142019

Reputation:

template<int a, int b, typename T = typename std::enable_if<a + b == 10>::type>
class foo {
};

This should do the job; just make sure you never explicitly provide the third template parameter when instantiating the template.


As others mentioned, static_assert is a much better fit.

Upvotes: 13

Sarang
Sarang

Reputation: 1897

I guess you can use static_assert better to enforce that constraint instead of enable_if

template<int a, int b>
class foo {
    static_assert(a+b==10, "a+b is not 10");
};

int main()
{
    foo<5,5> f; // will compile
    foo<1,5> f; // will fail to compile with error: a+b is not 10
    return 0;
}

enable_if is primarily used to conditionally remove functions and classes from overload resolution based on type traits and to provide separate function overloads and specializations for different type traits.

Upvotes: 12

Related Questions