I have a function with two template parameters
template<class X, class Y>
bool fun(X x, Y y) { ... }
I need to restrict second parameter to the following two cases: int y
or vector<int> const& y
. If I try to static_assert
:
static_assert( std::is_same<int, Y>::value ||
std::is_same<std::vector<int> const&, Y>::value,
"unsupported Y class" );
Then the following does not compile
X x;
std::vector<int> y;
fun(x, y);
because Y is deduced to be vector<int>
instead of vector<int> const&
.
Is there a way to restrict Y the way I want?
PS: Of course, I can call fun<X, vector<int> const&>( x, y )
but I want automatic type deduction to work. Or I can copy and paste and have two functions respectively, but it is a long function with same body, which I keep changing, so I don't like synchronizing two copies.
Y
will never be deduced as const vector<int>&
. That will only happen if that type is explicitly provided by the user.
X x;
std::vector<int> y;
fun(x, y); // Y deduced as std::vector<int>
fun<X, const std::vector<int>&>(x, y); // Y deduced as const std::vector<int>&
So if you don't expect types to be used explicitly, you can just static_assert
against the expected types:
static_assert( std::is_same<int, Y>::value ||
std::is_same<std::vector<int>, Y>::value,
"unsupported Y class" );
However, if you want to handle even the case where the caller provides the types explicitly, then you want to use std::decay
:
using dY = typename std::decay<Y>::type;
That will drop the const
and &
qualifiers. And then, you can do your static assert with neither:
static_assert( std::is_same<int, dY>::value ||
std::is_same<std::vector<int>, dY>::value,
"unsupported Y class" );
It sounds like you want to be able to pass in anything that's implicitly convertible to int
or const std::vector<int>&
, but you want the actual parameter type to be int
or const std::vector<int>&
, and you don't want to repeat the implementation. So, do this:
template <class X, class Y>
bool actual_fun(X x, Y y) {
// actual implementation
}
template <class X>
bool fun(X x, int y) {
return actual_fun<X, int>(x, y);
}
template <class X>
bool fun(X x, const std::vector<int>& y) {
return actual_fun<X, const std::vector<int>&>(x, y);
}
(You may want to wrap actual_fun
in a namespace detail
or something of that sort.)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.