c++ enable_if for non-type template parameters

You can totally do what you want with enable_if, just remember, the substitution has to fail when the condition is false, so you must call type to ensure the substitution fails when specializing for various conditions.

#include <stdio.h>
#include <iostream>
#include <type_traits>

template <typename T, int DIM>
class foo
{
public:
    template <int D = DIM>
    typename std::enable_if<D == 1, T>::type
    function()
    {
        // do something
        return 1.0;
    }

    template <int D = DIM>
    typename std::enable_if<D == 2, T>::type
    function()
    {
        // do something else
        return 2342.0;
    }

};

int main(){
    foo<int, 1> object;
    int ak = object.function();
    std::cout << ak << "\n";

    return 0;
}

For simple scenarios, like the one above (where you check a specific value, rather than a range of values), you can also use partial specialization. But if you would like to specialize, say, for all values from 1-50, another for 51-200, and then a generic fallthrough, enable_if works great.

You can also use enable_if in the template signature. Just a quick example.

#include <stdio.h>
#include <iostream>
#include <type_traits>

template <typename T, int DIM>
class foo
{
public:
    template <int D = DIM, typename std::enable_if<D == 1, void>::type* = nullptr>
    T function()
    {
        // do something
        return 1.0;
    }

    template <int D = DIM, typename std::enable_if<D == 2, void>::type* = nullptr>
    T function()
    {
        // do something else
        return 2342.0;
    }

};

int main(){
    foo<int, 1> object;
    int ak = object.function();
    std::cout << ak << "\n";

    return 0;
}

You can partial specialize the whole class:

template <typename T, int DIM>
class foo;

template <typename T>
class foo<T, 1>
{
public:
    T function() {
         // do something
         return 1.0;
     }
};

template <typename T>
class foo<T, 2>
{
public:
    T function() {
         // do something
         return 2342.0;
     }
};

If you have lot of common code between both specialization, you may still use inheritance (inherit from common part or just the specialized part).

An easy alternative way is to use Tag dispatching:

template <typename T, int dim>
class foo
{
public:
    T function();
};

 template <typename T>
 T function_helper(foo<T, 1>&) {
     // do something
     return 1.0;
 }

 template <typename T>
 T function_helper(foo<T, 2>&) {
     // do something
     return 2342.0;
 }

template <typename T, int dim>
T foo::function() {
    return function_helper(*this);
}

But in C++17, if constexpr allows simpler syntax:

template <typename T, int DIM>
class foo
{
public:
    T function() {
        if constexpr (DIM == 1) {
            // do something
            return 1.0;
        } else if constexpr (DIM == 2) {
            // do something
            return 2342.0;
        }
    } 
};