Overloading based on non-type template parameter

主宰稳场 提交于 2019-12-12 08:09:22

问题


We are familiar with overloading based on function parameters. But why can't we have overloading based on non-type template parameters? With such overloading, you don't have to add extra function parameters just for overloading purposes, which may have a negative impact on runtime performance. Alas, the following code does not compile:

template <bool>
void func() {}

template <int>
void func() {}

int main() {
  func<0>();
}

The error message produced is

error: call of overloaded 'func()' is ambiguous
       func<0>();
               ^
note: candidate: void func() [with bool <anonymous> = false]
     void func() {}
          ^
note: candidate: void func() [with int <anonymous> = 0]
     void func() {}
          ^

Note that this may be more efficient than

void func(bool) {}

void func(int) {}

Is there any problem in allowing this usage?


回答1:


If you are open to a bit of added syntax, you can use:

// No default implementation.
template <typename T, T value> struct Impl;

// Implement the bool/true version
template <> struct Impl<bool, true>
{
   void operator()() {}
};

// Implement the bool/false version
template <> struct Impl<bool, false>
{
   void operator()() {}
};

// Implement the int version
template <int N> struct Impl<int, N>
{
   void operator()() {}
};

template <typename T, T value>
void func()
{
   Impl<T, value>()();
};

int main()
{
   func<bool, true>();
   func<int, 10>();
}

Disclaimer

I have no idea whether this will perform better than calling func(true).




回答2:


Andrei Alexandrescu wrote about this in "Modern C++ Design", IIUC, and it looks like std::integral_constant can basically give nearly the effect you want, no? What would be the major improvements over the following? It basically allows to overload on (at least integral types of) constants.

#include <type_traits>


using tt = std::integral_constant<bool, true>;
constexpr tt t;
using ft = std::integral_constant<bool, false>;
constexpr ft f;


void func(tt) {};

void func(ft) {};


int main()
{
    func(t);
    return 0;
}



回答3:


Why would you want to do that?

Templates are meant and designed for cases when the behavior of function is similar when having different types (such as finding a maximum value, as long as the operator '>' is supported for that type, you can find the maximum value. Doesn't matter whether it's an int or a float and such).

You should just overload it and not worry about the impact, it is not as bad as you might think. If the behavior is different enough between the functions, you shouldn't bother using templates



来源:https://stackoverflow.com/questions/34972679/overloading-based-on-non-type-template-parameter

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