C++ 函数模板的模糊重载

C++ 函数模板的模糊重载,c++,templates,overloading,C++,Templates,Overloading,此(人为)代码: 它产生了预期的结果: $ ./a.out first bar() second bar() 当我在main()中将模板类型从bool更改为int时: intmain() { Foo-f1(0); Foo f2=bar(true,f1);//第一个bar() Foo f3=bar(10,f1);//第二个bar() (void)f2;//避免未使用变量的警告 (void)f3;//避免未使用变量的警告 返回0; } 我得到一个编译错误: $ g++ -std=c++11 -

此(人为)代码:

它产生了预期的结果:

$ ./a.out 
first bar()
second bar()
当我在
main()
中将模板类型从
bool
更改为
int
时:

intmain()
{
Foo-f1(0);
Foo f2=bar(true,f1);//第一个bar()
Foo f3=bar(10,f1);//第二个bar()
(void)f2;//避免未使用变量的警告
(void)f3;//避免未使用变量的警告
返回0;
}
我得到一个编译错误:

$ g++ -std=c++11 -Wall -Wextra foo.cpp 
foo.cpp: In function 'int main()':
foo.cpp:30:29: error: call of overloaded 'bar(int, Foo<int>&)' is ambiguous
foo.cpp:30:29: note: candidates are:
foo.cpp:13:8: note: Foo<T> bar(const T&, const Foo<T>&) [with T = int]
foo.cpp:20:8: note: Foo<T> bar(int, const Foo<T>&) [with T = int]
$g++-std=c++11-Wall-Wextra foo.cpp
foo.cpp:在函数“int main()”中:
foo.cpp:30:29:错误:重载“bar(int,foo&)”的调用不明确
foo.cpp:30:29:注:候选人有:
foo.cpp:13:8:注:foo-bar(const T&,const-foo&)[带T=int]
foo.cpp:20:8:note:foo-bar(int,const-foo&)[带T=int]
问题是在这种情况下,
bar()
的两个版本发生冲突,编译器无法决定选择哪个版本

如何解决这个问题?

标签分发:

struct selector {};

template<typename T>
Foo<T> bar(const T& /*x*/, const Foo<T>& /*foo*/, const selector&)
{
    std::cout << "first bar()" << std::endl;
    return Foo<T>(1);
}

// call it
bar(1, f1, selector{});
struct选择器{};
模板
Foo-bar(常量T&/*x*/,常量Foo&/*Foo*/,常量选择器&)
{

std::cout您可以使用struct的部分模板专门化,例如:

namespace detail
{
    template <typename T1, typename T2> struct bar;

    template <typename T> struct bar<T, T>
    {
        Foo<T> operator()() const
        {
            std::cout << "first bar()" << std::endl;
            return Foo<T>(1);
        }
    };

    template <typename T> struct bar<int, T>
    {
        Foo<T> operator()() const
        {
            std::cout << "second bar()" << std::endl;
            return Foo<T>(42);
        }
    };

    template <> struct bar<int, int>
    {
        Foo<int> operator()() const
        {
            std::cout << "third bar()" << std::endl;
            return Foo<int>(42);
        }
    };

}


template<typename T1, typename T2>
Foo<T2> bar(const T1& /*x*/, const Foo<T2>& /*foo*/)
{
    return detail::bar<T1, T2>()();
}
名称空间详细信息
{
模板结构条;
模板结构栏
{
Foo运算符()()常量
{

如果你可以使用参数给出选择选项,你可以选择你想要使用的条,这可以消除歧义。我希望这能有所帮助

#include <iostream>

template<typename T> class Foo
{
public:
    Foo(int i) : i_(i) {}

private:
    int i_;
};

template<typename T>
Foo<T> bar(const T& /*x*/, const Foo<T>& /*foo*/,int pick=0)
{
    std::cout << "first bar()" << std::endl;
    return Foo<T>(1);
}

template<typename T>
Foo<T> bar(int /*x*/, const Foo<T>& /*foo*/,double pick=0)
{
    std::cout << "second bar()" << std::endl;
    return Foo<T>(42);
}

int main()
{
    Foo<bool> f1(0);
    Foo<int> f15(0);
    Foo<bool> f2 = bar(true, f1); // first bar()
    Foo<int> f3 = bar(10, f15,1); // first bar()
    Foo<int> f35 = bar(10, f15,1.0); // second bar()
    (void)f2; // avoid warning for unused variable
    (void)f3; // avoid warning for unused variable
    return 0;
}
#包括
模板类Foo
{
公众:
Foo(inti):i_u(i){}
私人:
国际组织;
};
模板
Foo-bar(常数T&/*x*/,常数Foo&/*Foo*/,int-pick=0)
{

std::cout Class Foo是一个模板类,但是参数被硬设置为int。它不应该是t吗?如果第一个参数应该是相同类型的t,那么就专门化,否则您的示例可能有点过于简化。由于两个函数做的事情不同,您可以重命名其中一个…如何解决这个问题?取决于您选择的函数,为什么呢?如果
T
int
,那只是一种专门化,不需要
启用\u If
struct selector {};

template<typename T>
Foo<T> bar(const T& /*x*/, const Foo<T>& /*foo*/, const selector&)
{
    std::cout << "first bar()" << std::endl;
    return Foo<T>(1);
}

// call it
bar(1, f1, selector{});
namespace detail
{
    template <typename T1, typename T2> struct bar;

    template <typename T> struct bar<T, T>
    {
        Foo<T> operator()() const
        {
            std::cout << "first bar()" << std::endl;
            return Foo<T>(1);
        }
    };

    template <typename T> struct bar<int, T>
    {
        Foo<T> operator()() const
        {
            std::cout << "second bar()" << std::endl;
            return Foo<T>(42);
        }
    };

    template <> struct bar<int, int>
    {
        Foo<int> operator()() const
        {
            std::cout << "third bar()" << std::endl;
            return Foo<int>(42);
        }
    };

}


template<typename T1, typename T2>
Foo<T2> bar(const T1& /*x*/, const Foo<T2>& /*foo*/)
{
    return detail::bar<T1, T2>()();
}
int main()
{
    Foo<int> f1(0);
    Foo<int> f2 = bar<int>(true, f1); // first bar()
    Foo<int> f3 = bar(10, f1); // second bar()
    (void)f2; // avoid warning for unused variable
    (void)f3; // avoid warning for unused variable
    return 0;
}
int main()
{
    Foo<bool> f1(0);
    Foo<bool> f2 = bar(true, f1); // first bar()
    Foo<bool> f3 = bar(10, f1); // second bar()
    (void)f2; // avoid warning for unused variable
    (void)f3; // avoid warning for unused variable
    return 0;
}
#include <iostream>

template<typename T> class Foo
{
public:
    Foo(int i) : i_(i) {}

private:
    int i_;
};

template<typename T>
Foo<T> bar(const T& /*x*/, const Foo<T>& /*foo*/,int pick=0)
{
    std::cout << "first bar()" << std::endl;
    return Foo<T>(1);
}

template<typename T>
Foo<T> bar(int /*x*/, const Foo<T>& /*foo*/,double pick=0)
{
    std::cout << "second bar()" << std::endl;
    return Foo<T>(42);
}

int main()
{
    Foo<bool> f1(0);
    Foo<int> f15(0);
    Foo<bool> f2 = bar(true, f1); // first bar()
    Foo<int> f3 = bar(10, f15,1); // first bar()
    Foo<int> f35 = bar(10, f15,1.0); // second bar()
    (void)f2; // avoid warning for unused variable
    (void)f3; // avoid warning for unused variable
    return 0;
}