将函数模板参数限制为某些类型
Restricting function template parameter to certain types
我有一个带有两个模板参数的函数
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 )
,但我希望自动类型推导起作用。或者我可以复制和粘贴,分别有两个函数,但它是一个长函数,主体相同,我一直在改变,所以我不喜欢同步两个副本。
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" );
听起来您希望能够传递任何可隐式转换为 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
或类似的东西中。)
我有一个带有两个模板参数的函数
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 )
,但我希望自动类型推导起作用。或者我可以复制和粘贴,分别有两个函数,但它是一个长函数,主体相同,我一直在改变,所以我不喜欢同步两个副本。
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" );
听起来您希望能够传递任何可隐式转换为 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
或类似的东西中。)