4

I have a the following class template

template<int N>
constexpr int arraySize() { return arraySize<N-1>() + N; }

template<>
constexpr int arraySize<0>() { return 0; }

template<int C>
class MyClass {
    public:
    std::array<int, arraySize<C>()> arr;
};

int main() {

    MyClass<3> cls;
    std::cout << cls.arr.size() << std::endl;    // Output: 6
}

Everything works but I would like to have calculateArraySize<N>() as a member function. I've tried the following:

template<int C>
class MyClass {
    public:

    static constexpr int arraySize();
    std::array<int, MyClass<C>::arraySize()> arr;
};

template<int C>
constexpr int MyClass<C>::arraySize(){ return MyClass<C-1>::arraySize() + C; }

template<>
constexpr int MyClass<0>::arraySize() { return 0; }

Results in the following error:

fatal error: recursive template instantiation exceeded maximum depth of 1024 std::array::arraySize()> arr;

template<int C>
class MyClass {
    public:

    template<int N>
    static constexpr int arraySize();
    std::array<int, MyClass::arraySize<C>()> arr;
};

template<int C>
template<int N>
constexpr int MyClass<C>::arraySize(){ return MyClass::arraySize<N-1>() + N-1; }

template<int C>
template<>
constexpr int MyClass<C>::arraySize<0>() { return 0; }

Gives the following error:

tmp.cc:19:27: error: cannot specialize (with 'template<>') a member of an unspecialized template constexpr int MyClass::arraySize<0>() { return 0; }

Is it possible to achieve the desired behaviour? Solutions using C++14/C++17 features (I guess it should be possible usinn if-constexpr) are welcomed but won't solve my particular problem since only C++11 is available.

8
  • 6
    Tip : The sum of the first N natural numbers (so 1+2+3+...+N) is N*(N+1)/2. Commented Feb 23, 2018 at 20:47
  • @FrançoisAndrieux yep, I know, thank you. My question is not only about this particular case, it's more like a simple example. Commented Feb 23, 2018 at 20:49
  • Then it's not clear to me what you are asking. If the problem is that you are exceeding the maximum depth, then the first solution is to reduce the recursion depth. Are you asking how to specialize a member function? Commented Feb 23, 2018 at 20:50
  • 1
    You cannot specialize a member function in C++, without specializing the whole class. Commented Feb 23, 2018 at 20:51
  • The second error idicates this. Is are any workaround? Commented Feb 23, 2018 at 20:52

2 Answers 2

4

You can move the function into the class and the specialize the entire class for the base case. That looks like:

template<int C>
class MyClass {
    public:

    static constexpr int arraySize(){ return MyClass<C-1>::arraySize() + C; }
    std::array<int, MyClass<C>::arraySize()> arr;
};

template<>
class MyClass<0> {
    public:
    static constexpr int arraySize(){ return 0; }
};

int main() {
    MyClass<3> cls;
    std::cout << cls.arr.size() << std::endl;    // Output: 6
}

Live Example

Sign up to request clarification or add additional context in comments.

1 Comment

@datell, keep in mind, this specialization does not inherit anything from template. I.e, if your template class MyClass<C>, for example, had a member int blah, specialization MyClass<C> as written would not have this member.
1

You can also use a member variable instead of a member function.

template <int C>
class MyClass {
   public:

      static constexpr int array_size = MyClass<C-1>::array_size + C;
      std::array<int, array_size> arr;
};

template <>
class MyClass<0> {
   public:
       static constexpr int array_size = 0;
};

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.