请考虑以下代码:
#include <utility>
#include <iostream>
struct S {
template<typename T, typename... A>
auto f(A&&... args) -> decltype(std::declval<T>().f(std::forward<A>(args)...), void()) {
std::cout << "has f(int)" << std::endl;
}
template<typename>
void f(...) {
std::cout << "has not f(int)" << std::endl;
}
};
struct T { void f(int) { } };
struct U { };
int main() {
S s;
s.f<T>(42); // -> has f(int)
s.f<U>(42); // -> has not f(int)
// oops
s.f<T>(); // -> has not f(int)
}
如示例所示,对f的第三次调用工作得很好,即使参数的数量是错误的,因为它对于回退函数完全没有错.
当省略号以这种方式涉及时,有没有办法强制参数的数量?
我的意思是,我可以在编译时检查参数列表的大小是否正好为1,无论是选择主函数还是后备函数?
良好的解决方案也只涉及第一个模板功能,并且由于参数包的大小而导致硬错误而不是软错误.
当然,它可以通过几种技术解决,而无需使用可变参数.举个例子:int / char调度内部模板方法;显式指定参数列表;随你…
问题不是关于做到这一点的替代方法,我已经知道了.
这只是要知道我是否遗漏了一些基本的东西,或者这是不可能的,这就是全部.
最佳答案 如果我正确理解您的问题,您可以添加一个图层:
struct S {
private:
template<typename T, typename... A>
auto f_impl(A&&... args)
-> decltype(std::declval<T>().f(std::forward<A>(args)...), void()) {
std::cout << "has f(int)" << std::endl;
}
template<typename>
void f_impl(...) {
std::cout << "has not f(int)" << std::endl;
}
public:
template<typename T, typename A>
auto f(A&& args) { return f_impl<T>(std::forward<A>(arg)); }
};
有了特质,你可以这样做
template <typename T, typename ... Ts>
using f_t = decltype(std::declval<T>().f(std::declval<Ts>()...));
template <typename T, typename ... Ts>
using has_f = is_detected<f_t, T, Ts...>;
struct S {
template<typename T, typename... A>
std::enable_if_t<has_f<T, A&&...>::value && sizeof...(A) == 1> f(A&&... args)
{
std::cout << "has f(int)" << std::endl;
}
template<typename T, typename... A>
std::enable_if_t<!has_f<T, A&&...>::value && sizeof...(A) == 1> f(A&&... args) {
std::cout << "has not f(int)" << std::endl;
}
};