我有一个带有两个模板参数的函数
template<class X, class Y>
bool fun(X x, Y y) { ... }
我需要将第二个参数限制为以下两种情况:int y
或vector<int> const& y
。如果我尝试static_assert
:
static_assert( std::is_same<int, Y>::value ||
std::is_same<std::vector<int> const&, Y>::value,
"unsupported Y class" );
然后以下不编译
X x;
std::vector<int> y;
fun(x, y);
因为Y推断为vector<int>
而不是vector<int> const&
。
有没有办法以我想要的方式限制Y?
PS:当然,我可以致电fun<X, vector<int> const&>( x, y )
,但我想要自动类型扣除工作。或者我可以分别复制和粘贴两个函数,但它是一个具有相同主体的长函数,我不断改变,所以我不喜欢同步两个副本。
答案 0 :(得分:0)
Y
永远不会被推断为const vector<int>&
。只有在用户明确提供该类型时才会发生这种情况。
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>&
因此,如果您不希望明确使用类型,则只能针对预期类型static_assert
:
static_assert( std::is_same<int, Y>::value ||
std::is_same<std::vector<int>, Y>::value,
"unsupported Y class" );
但是,如果您想要处理调用者明确提供类型的情况,那么您要使用std::decay
:
using dY = typename std::decay<Y>::type;
这会删除const
和&
限定词。然后,您可以使用以下两者执行静态断言:
static_assert( std::is_same<int, dY>::value ||
std::is_same<std::vector<int>, dY>::value,
"unsupported Y class" );
答案 1 :(得分:0)
听起来您希望能够传递任何可隐式转换为int
或const std::vector<int>&
的内容,但您希望实际参数类型为int
或const std::vector<int>&
,您不想重复执行。所以,这样做:
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);
}
(您可能希望将actual_fun
包裹在namespace detail
或类似的内容中。)