gsf
gsf

Reputation: 7252

division by zero with a template argument

I have a template

template<size_t N>
class Foo {
    int bar(int a) {
        if (N == 0)
            return 0;
        return a / N;
    }
 }

when I instantiate this with 0

Foo<0> bar;

gcc is too smart and reports division by zero at compile time

I tried

class Foo<size_t N> {
    template<size_t M>
    int bar(int a) {
        return a / N;
    }

    template<>
    int bar<0>(int a) {
        return 0;
    }
 };

but this gives me error:

error: explicit specialization in non-namespace scope 'class Foo' error: template-id 'bar<0>' in declaration of primary template

any ideas how I could solve/workaround this?

Upvotes: 6

Views: 612

Answers (3)

jxh
jxh

Reputation: 70422

You can create a template specialization for Foo<0>.

template <>
class Foo<0> {
public:
    bool bar () { return true; }
};

If you only want to address the issue with bar alone, and not touch any other part of Foo, you can create a companion method to avoid the issue:

template <size_t N>
class Foo
{
    bool bar(int n) {
        if (n == 0) return true;
        return 5 / n == 1;
    }
public:
    bool bar() { return bar(N); }
};

Or pull the implementation of that method out into its own class, and specialize that:

template <size_t N>
class Bar
{
public:
    bool operator() const { return 5 / N == 1; }
};

template <>
class Bar<0>
{
public:
    bool operator() const { return true; }
};

template <size_t N>
class Foo {
    bool bar() { return Bar<N>()(); }
};

Alternatively, you can use Jarod42's suggestion, and specialize the method itself (answer reiterated here for completeness).

template <size_t N>
class Foo
{
public:
    bool bar() { return 5 / N == 1; }
};

template <> inline bool Foo<0>::bar() { return true; }

Upvotes: 4

Jarod42
Jarod42

Reputation: 217438

You may specialize the method:

template <size_t N> class Foo
{
public:
    bool bar()
    {
        return 5 / N == 1;
    }
};

template <>
bool Foo<0>::bar() { return true; }

Live example

To avoid multiple definitions, you have to define the function only once, or use inline, so

// In header
template <>
inline bool Foo<0>::bar() { return true; }

or

// In header: declaration of the specialization
template <>
bool Foo<0>::bar();

// in cpp: definition of the specialization.
template <>
bool Foo<0>::bar() { return true; }

Upvotes: 3

Eclipse
Eclipse

Reputation: 45493

You can always rethink the formula:

template<size_t N>
class Foo {
    bool bar() {
        return N == 0 || (N >=5 && N < 10);
    }
 }

Upvotes: 5

Related Questions