In general, you can do it. For instance:
int i = 0;
double d = 3.14;
i = static_cast<decltype(i)>(d);
However, keep in mind your function returns a reference (because decltype(*(c.begin()))
evaluates to a reference type):
std::vector<int> v;
static_assert(std::is_same<decltype(*v.begin()), int&>::value, "!"); // Won't fire
What's troublesome in this situation is that the function must be able to return a reference to an object of type Container::value_type
, but if somevalue
has a different type, you won't be able to return a reference to it as a Container::value_type&
.
The reason is the same why you are not allowed to do the following:
int i = 42;
float& f = static_cast<float&>(i);
So the first thing you need to ask yourself is whether your findInposition()
function should really return a reference to the element of the collection (in which case, what you want to do is not possible, just like the example above), or rather return by value a copy of that element.
If that is the case, and you insist on using decltype
, you may transform the output of decltype
through std::decay
:
#include <type_traits>
template<typename Container>
auto findInposition(Container& c,int position) ->
typename std::decay<decltype(*c.begin())>::type
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
{
if(std::distance(c.begin(),c.begin()+position)<c.size())
return c.at(position);
else
return static_cast<
typename std::decay<decltype(*c.begin())>::type>(somevalue);
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
}
But in my opinion the following is much clearer:
template<typename Container>
auto findInposition(Container& c,int position) ->
typename Container::value_type
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
{
if(std::distance(c.begin(),c.begin()+position)<c.size())
return c.at(position);
else
return static_cast<typename Container::value_type>(somevalue);
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
}