问题
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