2014-03-13 65 views
1

是否可以使用operator<<按照原样编写以下print函数。我有一些图像数据可能以各种方式存储,包括无符号字符。打印时,我想将unsigned char的值转换为int,以便正确显示。但是,我只需要为unsigned char指定一个类型,所以我使用默认的模板参数。将多个模板类型传递给<< C++中的运算符<<

我用std::vector说明的目的。这实际上是一个包含像素数据的缓冲区,我不能在运行时确定它的类型,所以我将始终指定源类型T

我知道我可以写在数据类型是unsigned char一个专业化,但不知道是否有可能合并成一个通用operator<<功能,可以与print

template<typename T, typename U = T> 
std::ostream& print(std::ostream& os, const std::vector<T>& vals) 
{ 
    for (auto v : vals) { 
     os << U{v} << ' '; // Warns on narrowing conversion. 
    } 

    return os; 
} 

使用类似下面的代码调用,

vector<unsigned char> vc{ 1, 2, 3 }; 
vector<int> vi{ 4, 5, 6 }; 

print<unsigned char, int>(vc); 
print<int>(vi); 

我试图与操作者< <更换打印,但该错误消息建议我用basic_ostream的声明(template <class charT, class traits = char_traits<charT>> class basic_ostream)冲突。

+0

@TemplateRex 我实际上已经与在函数体下面, '使用U =类型名称的std ::条件<性病:: is_same ::值,整型,T>: :type;' 并删除了模板参数。模板参数不会出现在Doxygen输出中,再加上它无法使用。 我可以推测,没有办法将U明确地传递给operator <<? –

+1

你可以但你需要写的东西。丑陋的'std.cout.operator <<(myvec)'也会抑制ADL,所以我宁愿避免这种情况。 – TemplateRex

+0

Yuck。在这种情况下,我不会因为拥有打印功能而失去任何东西。谢谢你的答案。 –

回答

2

在C++ 11中,您可以使用简单的std::conditionalstd::is_same<T, unsigned char>作为默认的模板参数,您无需重写。这意味着您可以使用熟悉的<<流语法

#include <iostream> 
#include <type_traits> 
#include <vector> 

template 
< 
    class T, 
    class U = typename std::conditional<std::is_same<T, unsigned char>::value, int, T>::type 
> 
std::ostream& operator<<(std::ostream& os, std::vector<T> const& vals) 
{ 
    for (auto v : vals) { 
     os << U{v} << ' '; 
    } 

    return os; 
} 

int main() 
{ 
    auto const vc = std::vector<unsigned char>{ 1, 2, 3 }; 
    auto const vi = std::vector<int>{ 4, 5, 6 };   

    std::cout << vc << "\n"; 
    std::cout << vi << "\n"; 
} 

Live example

如果你被绑定到C++ 98,有Boost equivalents