如何为元组参数专门化一个函数?
How to specialize a function for a tuple parameter?
我有以下功能:
template <typename Functor, typename Arg>
decltype(auto) call(Functor f, Arg &&arg) { // (1)
// ..
}
我想为 arg
是 tuple
的情况创建一个专业化。我试过了:
template <typename Functor, typename... Args>
decltype(auto) call(Functor f, std::tuple<Args...> &&args) { // (2)
// ..
}
它可以单独使用,但是当两者都存在时,即使参数是元组,(1) 也会更好地匹配。我正在使用 clang 3.7 来编译代码。
我发现您的示例确实有效(并且 vs2015 同意)
基本情况是通用引用,它同时采用右值和右值(和引用)。 (现场演示 http://ideone.com/kCBv3d)
decltype(auto) call(int &&arg) { // (1)
std::cout << "Base case" << std::endl;
}
decltype(auto) call(std::tuple<int> &&args) {
std::cout << "TTT" << std::endl;
}
/// main:
call(std::tuple<int>{1}); // TTT
call(2); // Base case
std::tuple<int> ti{5};
call(1,ti); // Base case (as expected!)
call(1,std::move(ti)); // TTT
请注意,您的重载采用右值引用(不是转发引用),因此任何其他内容(左值引用)都将使用基本情况。
据我所知,这都是超载,但相关的阅读是 Herb Sutter 的 post:http://www.gotw.ca/publications/mill17.htm
如果您想避免编写丑陋的 SFINAE,您将需要执行一级间接寻址。除了标签调度,您还可以委托给 class 模板,但我更喜欢标签
template<typename> class type { };
template <typename Functor, typename Arg>
decltype(auto) call(Functor f, Arg &&arg) {
return call(f, std::forward<Arg>(arg), type<std::decay_t<Arg>>());
}
template <typename Functor, typename Arg, typename T>
decltype(auto) call(Functor f, Arg &&arg, type<T>) {
...
}
template <typename Functor, typename Arg, typename ...T>
decltype(auto) call(Functor f, Arg &&arg, type<std::tuple<T...>>) {
...
}
我有以下功能:
template <typename Functor, typename Arg>
decltype(auto) call(Functor f, Arg &&arg) { // (1)
// ..
}
我想为 arg
是 tuple
的情况创建一个专业化。我试过了:
template <typename Functor, typename... Args>
decltype(auto) call(Functor f, std::tuple<Args...> &&args) { // (2)
// ..
}
它可以单独使用,但是当两者都存在时,即使参数是元组,(1) 也会更好地匹配。我正在使用 clang 3.7 来编译代码。
我发现您的示例确实有效(并且 vs2015 同意)
基本情况是通用引用,它同时采用右值和右值(和引用)。 (现场演示 http://ideone.com/kCBv3d)
decltype(auto) call(int &&arg) { // (1)
std::cout << "Base case" << std::endl;
}
decltype(auto) call(std::tuple<int> &&args) {
std::cout << "TTT" << std::endl;
}
/// main:
call(std::tuple<int>{1}); // TTT
call(2); // Base case
std::tuple<int> ti{5};
call(1,ti); // Base case (as expected!)
call(1,std::move(ti)); // TTT
请注意,您的重载采用右值引用(不是转发引用),因此任何其他内容(左值引用)都将使用基本情况。
据我所知,这都是超载,但相关的阅读是 Herb Sutter 的 post:http://www.gotw.ca/publications/mill17.htm
如果您想避免编写丑陋的 SFINAE,您将需要执行一级间接寻址。除了标签调度,您还可以委托给 class 模板,但我更喜欢标签
template<typename> class type { };
template <typename Functor, typename Arg>
decltype(auto) call(Functor f, Arg &&arg) {
return call(f, std::forward<Arg>(arg), type<std::decay_t<Arg>>());
}
template <typename Functor, typename Arg, typename T>
decltype(auto) call(Functor f, Arg &&arg, type<T>) {
...
}
template <typename Functor, typename Arg, typename ...T>
decltype(auto) call(Functor f, Arg &&arg, type<std::tuple<T...>>) {
...
}