如何使用SFINAE调度到模板化的调用操作符

时间:2017-09-12 02:40:58

标签: c++ c++14 sfinae typetraits

我有一个带有模板化可调参数的函数,并将索引传递给它。在某些情况下,我希望静态传递该索引(我正在使用元组)。我认为通过使用模板化调用操作符并使用SFINAE传递可调用对象应该可以实现这一点。

首先,这看起来像:

struct A {
    template< size_t I >
    void operator()( int x )
    {
        cout << "A " << x << " " << I << endl;
    }
};

struct B {
    void operator()( int x, int i )
    {
        cout << "B " << x << " " << i << endl;
    }
};


template<
    typename F,
    size_t I = 0
>
inline
void
call( int x, F & fn ) {
    fn( x, I );
}


int main()
{
    A a;        
    B b;

    call( 2, b );
    call< B, 3 >( 2, b );

    call( 1, a ); // no match for call to '(A) (int&, long unsigned int)'

    return 0;
}

所以我尝试重载调用函数并使用SFINAE选择正确的调用:

template<
    typename F,
    size_t I = 0
>
inline
typename std::enable_if< /* I've tried all kinds of things here */ >::type
call( int x, F & fn ) {
    fn< I >( x );
}

但我无法弄清楚用于检测F是否可以使用一个模板参数和一个int参数调用的类型特征。我一直在引用this articlethis one,但我很难适应我的用例。有任何想法吗?是否可以不修改呼叫站点?

1 个答案:

答案 0 :(得分:2)

struct A {
  template< std::size_t I >
  void operator()( int x, std::integral_constant<std::size_t, I> i ) {
    cout << "A " << x << " " << I << endl;
  }
};

请改用它。标准SFINAE测试工作,没有传递模板非类型参数。

在C ++ 14编译器中,您可以std::get<i>。在C ++ 11编译器中,您可以std::get<I>std::get<decltype(i)::value>

传递模板非类型参数很糟糕。避免它们。