c++ - 是否可以重载模板函数以与 std::vector 的元素一起使用?

标签 c++ c++11 templates polymorphism stdvector

我正在尝试让一个函数采用通用 std::vector (template<typename T> std::vector<T> ,然后调用一个模板函数,该函数在其所有元素上都具有针对特定(抽象)类型的特化

我正在尝试弄清楚如何使用专用版本,同时仍然能够使用通用版本,但我没有成功。

我使用的是 visual studio 2019。

这是我的代码:

#include <iostream>
#include <vector>

//the abstract type
struct Foo
{
    virtual int bar(unsigned int) const = 0;
};

//The 'template function' I mentioned
template<typename T>
void do_something_with_an_element(const T& value)
{
    std::cout << value;
}

//the specialised version I mentioned
template<>
void do_something_with_an_element<Foo>(const Foo& value)
{
    //Note: this is only a placeholder
    std::cout << "It's a foo. bar = " << value.bar(7) << std::endl;
}

//the function that takes the 'generic' std::vector
template<typename T>
void do_something_with_a_vector(const std::vector<T>& vec)
{
    for (auto element : vec)
    {
        //calling the function on all its elements
        do_something_with_an_element(element); //Here is the problem line
    }
}

struct foo_impl : public Foo
{
    int val;

    foo_impl(int _val)
        : val(_val)
    {}

    // Inherited via Foo
    virtual int bar(unsigned int _something) const override
    {
        //do whatever...
        return val;
    }
};

std::vector<int> int_vector = { 32, 3, 43, 23 }; 
std::vector<foo_impl> foo_vector = { foo_impl(3), foo_impl(9), foo_impl(13) };

int main()
{
    do_something_with_a_vector(int_vector); //fine
    do_something_with_a_vector(foo_vector); //compile error
}


这是我的错误:

        1>program.cpp
        1>C:\...\program.cpp(17): error C2679: binary '<<': no operator found which takes a right-hand operand of type 'const T' (or there is no acceptable conversion)
        1>        with
        1>        [
        1>            T=foo_impl
        1>        ]
        1>C:\...\MSVC\14.20.27508\include\ostream(438): note: could be 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(std::basic_streambuf<char,std::char_traits<char>> *)'
        1>C:\...\MSVC\14.20.27508\include\ostream(413): note: or       'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(const void *)'
         ((list goes on...))
        1>C:\...\program.cpp(17): note: while trying to match the argument list '(std::ostream, const T)'
        1>        with
        1>        [
        1>            T=foo_impl
        1>        ]
        1>C:\...\program.cpp(35): note: see reference to function template instantiation 'void do_something_with_an_element<foo_impl>(const T &)' being compiled
        1>        with
        1>        [
        1>            T=foo_impl
        1>        ]
        1>C:\...\program.cpp(61): note: see reference to function template instantiation 'void do_something_with_a_vector<foo_impl>(const std::vector<foo_impl,std::allocator<_Ty>> &)' being compiled
        1>        with
        1>        [
        1>            _Ty=foo_impl
        1>        ]
        1>Done building project "program.vcxproj" -- FAILED.
        ========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========```

最佳答案

为了选择专业 const Foo& , 从 foo_impl 隐式转换至 Foo应该发生。另一方面,通过选择 const T&编译器做了一个聪明的举动,它直接推导出类型(即 foo_impl ),因为这对编译器来说更容易。

因此 Foo 的特化被拒绝,错误出现是因为未找到 operator<<(std::cout, foo_impl) 的过载.


更新:为了选择正确的特化,通过阻止编译器实例化 const T&对于 foo_impl ,您可以将 SFINAE 与重载解析一起使用。 (创作者@Hiroki)

template<typename T>
std::enable_if_t<!std::is_base_of_v<Foo, T>>
do_something_with_an_element(const T& value)
{
    std::cout << value;
}

void do_something_with_an_element(const Foo& value)
{
    std::cout << "It's a foo. bar = " << value.bar(7) << std::endl;
}

关于c++ - 是否可以重载模板函数以与 std::vector 的元素一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55771614/

相关文章:

c++ - 获取 std::array 的第二个参数(大小)作为函数参数

c++ - 在不使用嵌套名称说明符的情况下定义 namespace 的成员的 clang 中是否存在错误

c++ - QObject::connect 的函数包装器

c++ - 用模板参数填充容器

c++ - 无法从C++ std::string中提取Unicode符号

c++ - 为什么 std::map::insert 不能采用键和值而不是 std::pair?

templates - node.js + express.js + dust.js 问题

c++ - 结构成员字段是函数指针时出错

c++ - C++/编译: is it possible to set the size of the vptr (global vtable + 2 bytes index)

c++ - 代码意外编译失败。为什么?