将函数模板参数限制为某些类型

时间:2015-02-08 04:11:24

标签: c++ templates

我有一个带有两个模板参数的函数

template<class X, class Y>
bool fun(X x, Y y) { ... }

我需要将第二个参数限制为以下两种情况:int yvector<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 ),但我想要自动类型扣除工作。或者我可以分别复制和粘贴两个函数,但它是一个具有相同主体的长函数,我不断改变,所以我不喜欢同步两个副本。

2 个答案:

答案 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)

听起来您希望能够传递任何可隐式转换为intconst std::vector<int>&的内容,但您希望实际参数类型为intconst 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或类似的内容中。)