如何为元组参数专门化一个函数?

How to specialize a function for a tuple parameter?

我有以下功能:

template <typename Functor, typename Arg>
decltype(auto) call(Functor f, Arg &&arg) { // (1)
    // ..
}

我想为 argtuple 的情况创建一个专业化。我试过了:

template <typename Functor, typename... Args>
decltype(auto) call(Functor f, std::tuple<Args...> &&args) { // (2)
    // ..
}

它可以单独使用,但是当两者都存在时,即使参数是元组,(1) 也会更好地匹配。我正在使用 clang 3.7 来编译代码。

我发现您的示例确实有效(并且 vs2015 同意)

http://ideone.com/dNTsrf

基本情况是通用引用,它同时采用右值和右值(和引用)。 (现场演示 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...>>) {
    ...
}