c++ - 额外的模板参数导致重载歧义

标签 c++ c++11

我正在尝试提取函数模板的详细信息作为模板参数。

#include <tuple>

template <typename T>
struct Generator
{
    typedef int type;
    int operator()(int i) const { return i; }
};

// old functions
template <
    typename... Args,
    typename... FArgs>
std::tuple<Args...> g(
    std::tuple<Args...> & a,
    FArgs&&... fargs)
{
    return std::make_tuple( (Generator<Args>()(fargs...))... );
}

template <
    typename Arg,
    typename... FArgs>
std::tuple<Arg> g(
    std::tuple<Arg> & a,
    FArgs&&... fargs)
{
    return std::make_tuple( (Generator<Arg>()(std::forward<FArgs>(fargs)...)) );
}

// new functions
template <
    template <typename T> class F,
    typename... Args,
    typename... FArgs>
std::tuple<Args...> h(
    std::tuple<Args...> & a,
    FArgs&&... fargs)
{
    return std::make_tuple( (F<Args>()(fargs...))... );
}

template <
    template <typename> class F,
    typename Arg,
    typename... FArgs>
std::tuple<Arg> h(
    std::tuple<Arg> & a,
    FArgs&&... fargs)
{
    return std::make_tuple( (F<Arg>()(std::forward<FArgs>(fargs)...)) );
}

int main()
{
    auto t = std::make_tuple( 1 );
    auto y = g(t, 2);
    auto z = h<Generator>(t, 2);  // ERROR
}

它用 clang 编译得很好,但是使用 gcc(4.9、5.3 和 6.2)我得到以下错误:

% g++ --std=c++11 test.cc
test.cc: In function ‘int main()’:
test.cc:56:28: error: call of overloaded ‘h(std::tuple<int>&, int)’ is ambiguous
  auto z = h<Generator>(t, 2);
                            ^
test.cc:34:21: note: candidate: std::tuple<_Elements ...> h(std::tuple<_Elements ...>&, FArgs&& ...) [with F = Generator; Args = {int}; FArgs = {int}]
 std::tuple<Args...> h(
                     ^
test.cc:45:17: note: candidate: std::tuple<Arg> h(std::tuple<Arg>&, FArgs&& ...) [with F = Generator; Arg = int; FArgs = {int}]
 std::tuple<Arg> h(

这应该是模棱两可的吗?如果是这样,为什么对 g 的调用也不是模棱两可的?

最佳答案

只需将您的新函数定义为:

template <
    template <typename T> class F,
    typename... Args,
    typename... FArgs>
std::enable_if_t<(sizeof...(Args)>1), std::tuple<Args...>> h(
    std::tuple<Args...> & a,
    FArgs&&... fargs)
{
    return std::make_tuple( (F<Args>()(fargs...))... );
}

template <
    template <typename> class F,
    typename Arg,
    typename... FArgs>
std::tuple<Arg> h(
        std::tuple<Arg> & a,
        FArgs&&... fargs)
{
    return std::make_tuple( (F<Arg>()(std::forward<FArgs>(fargs)...)) );
}

这将允许消除歧义并实际编译您的代码。

事实上,h 的实现都以一个tuple 和一个int 作为参数,一个tuple > 只有一种类型对它们都有效。
sfinae 表达式(参见 enable_if_t)在这种情况下强制选择 h 的第二个实现,所有其他实现都是第一个。

关于c++ - 额外的模板参数导致重载歧义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39670058/

相关文章:

c++ - MSVC 中 std::vector::push_back 的实现

c++ - MFC 类和 C++ 样式转换

c++ - 使用 Xerces C++ 对 DOM 部分进行 XML 序列化

c++ - uniform_real_distribution 没有给出均匀分布

c++ - 将参数传递给模板函数的方法

c++ - 从 boost spirit x3 解析器返回的 vector 中的空字符串

c++ - 在此示例中,在对类的引用之前使用 * 运算符是什么意思

c++ - QMatrix4x4 模型 View 投影 OpenGL 无法获取要渲染的场景

c++ - 将 std::function 用于 API(跨模块边界)

C++11 是否所有的控制路径都需要返回值?