SFINAE和参数数量

时间:2017-12-17 19:46:22

标签: c++ templates sfinae

我有一个模板类SELECT [Room Number], DATEDIFF("d", min(CheckInDate), max(CheckOutDate)) as dif FROM Reservations GROUP by [Room Number] ,我打算用C<T>实例化其他类TAB有一个方法C<T>我的签名我想依赖于foo是否被TA实例化。例如,请考虑以下代码:

B

这正确运行。 #include <iostream> #include <string> class A { public: void message() { std::cout << "message with no args" << std::endl; } }; class B { public: void message(int x) { std::cout << "message with " << x << std::endl; } }; template<typename T> class C { private: T internal; public: C(T& x) { internal = x; } void call() { internal.message(); } void call(int x) { internal.message(x); } }; int main(int argc, char* argv[]) { A a; B b; C<A> ca(a); C<B> cb(b); ca.call(); cb.call(42); // ca.call(42); ERROR HERE return 0; } 会引发编译错误,因为没有方法ca.call(42)。但是,如果我出于某种原因在A::message(int)中引入方法A::message(int),则代码可能允许调用A,我想阻止它。

我知道SFINAE技术允许声明方法ca.call(42),其中C::call(T::call_type x)将是T::call_type的每个预期实例化的typedef。但是,这只允许我更改T参数的类型。我希望在C::call上创建{em>签名(特别是参数数量)C::call。因此,即使T中有方法ca.call(42),我也会阻止A::message(int)成为有效的通话。

有没有办法做到这一点?

2 个答案:

答案 0 :(得分:1)

我不知道SFINAE的所有细节,但你怎么看待这个?

template <
    typename = std::enable_if_t<std::is_same<std::decay_t<T>, A>::value>>
void call() {
    internal.message();
}
template <
    typename = std::enable_if_t<std::is_same<std::decay_t<T>, B>::value>>
void call(int x) {
    internal.message(x);
}

您也可以使用== false

template <
    typename = std::enable_if_t<std::is_same<std::decay_t<T>, B>::value == false>>

答案 1 :(得分:0)

您可以使用模板专业化来执行此操作:

// Main template used by every other type T.
template<typename T>
class C; // or some other implementation.

// This gets used for T = A.
template<>
class C<A> {
private:
    A internal;
public:
    C(A& x) {
        internal = x;
    }
    void call() {
        internal.message();
    }
};

// This gets used for T = B.
template<>
class C<B> {
private:
    B internal;
public:
    C(B& x) {
        internal = x;
    }
    void call(int x) {
        internal.message(x);
    }
};

如果您不喜欢,您需要复制一些常用代码,那么您可以拥有一个包含所有这些常见内容的基类,并在每个专门化中继承它。