Is There a Way to Declare a typename for a Templatized Function?

我们两清 提交于 2019-12-11 09:30:31

问题


So, I have this templatized function (which I know is ugly to look at.)

My intention was not to default the template parameter though, my intention was to create a typename derived from T that could be used in caster that the user could not assign to.

My question is how do I create a typename for a templatized function which the user cannot pass as an argument?

As an example:

template <typename T>
typename R = std::conditional<sizeof(T) == 4, char, short>;
R foo(T bar){return R(bar);}

Clearly this code doesn't compile, but that's the behavior I'd like to accomplish. Is a functor the only way to do this?


回答1:


In C++14, this is elegantly solved using return type deduction.

// C++14
#include <type_traits>

template <typename T>
decltype(auto)
foo(T bar)
{
  using R = std::conditional_t<sizeof(T) == 4, char, short>;
  return static_cast<R>(bar);
}

In C++11, you'd have to repeat the type computation.

// C++11
#include <type_traits>

template <typename T>
typename std::conditional<sizeof(T) == 4, char, short>::type
foo(T bar)
{
  using R = typename std::conditional<sizeof(T) == 4, char, short>::type;
  return static_cast<R>(bar);
}

This can be shortened a little by using decltype to figure out the type.

// C++11
#include <type_traits>

template <typename T>
typename std::conditional<sizeof(T) == 4, char, short>::type
foo(T bar)
{
  using R = decltype(foo(bar));
  return static_cast<R>(bar);
}

But frankly, what is wrong with using a simple default type parameter?

// C++11
#include <type_traits>

template <typename T,
          typename R = typename std::conditional<sizeof(T) == 4, char, short>::type>
R
foo(T bar)
{
  return static_cast<R>(bar);
}

Note that I have replaced the value initialization of R in your return statement with a static_cast to silence the compiler warning about the narrowing conversion. Are you sure that this is what you want, though?




回答2:


One possibility is to use using type alias instead of typename. The following code compiles on the compiler I tested (remember to enable -std=c++11 flag).

#include <type_traits>
#include <iostream>

// C++11
template <typename T>
using R = typename std::conditional<sizeof(T) == 4, char, short>::type;

template <typename T>
R<T> foo(T bar){return R<T>(bar);}

int main() {
  std::cout << foo(13.0) << std::endl;
  return 0;
}

In C++14, you can use the conditional_t trait, which is even simpler.

// C++14
template <typename T>
using R = std::conditional_t<sizeof(T) == 4, char, short>;


来源:https://stackoverflow.com/questions/28680634/is-there-a-way-to-declare-a-typename-for-a-templatized-function

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