Partial member function template specialisation and data member access

梦想的初衷 提交于 2019-12-01 06:21:30

As commented, you don't need to use partial specialization for this at all, indeed partial specialization is usually pretty easy to avoid, and preferred to avoid.

private:
template <class T>
struct tag{}; // trivial nested struct

template <class I, class T> 
void push_impl(I first, I last, tag<T>) { ... } // generic implementation

template <class I, class T>
void push_impl(I first, I last, tag<std::complex<T>>) { ... } // complex implementation

public:
template <class InputIt>
void push(InputIt first, InputIt last)
{
    push_impl(first, last,
              tag<typename std::iterator_traits<InputIt>::value_type> {});
}

Since push_impl is a (private) member function you don't need to do anything special any more.

Compared to your proposed solutions, this has no extra performance cost. It's the same number of function calls, the only difference is passing a stateless type by value, which is a wholly trivial optimization for the compiler. And there's no sacrifice in encapsulation either. And slightly less boilerplate.

push_impl can be made either an inner class template (if you use c++11) or a friend class template of your accumulator class (this seems like a good case for using friend declarations, since push_impl is essentially an integral part of your accumulator class implementation, separated purely for language reasons). Then you can use your option #3 (passing this to static methods of push_impl), but without making accumulator members public.

Option #4 doesn't seem too bad either (since it avoids code duplication), but as you mentioned the performance impacts would need to be measured.

Personally I'd be likely to choose your option 4, after all the only part of the iterator version that actually varies with type is the logic in the "single value version"

However another option is to write your iterator versions to receive the mean and size by reference, mean and size can then be updated without them having to be made public.

This will also help with testing as it allows push_impl to be tested separately (although with this approach you might consider that's no longer the best name for the function)

As an aside, it would be better for your push_impl to be templated only on iterator type, you can deduce the value type inside push_impl in the same way that you currently so in your calling example, but with only the iterator type as a parameter there's no chance of accidently calling it with the wrong value type (which might not always cause a compilation error if the value type can be converted to the type you pass as "T")

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!