2013-07-26 37 views
2

在C++中,我试图为std::set编写operator<<的模板版本,这样我就不必为包含的值类型的每个排列编写一个模板。如何为运算符创建C++模板<<

我定义我的头为utils.h

#ifndef UTILS 
#define UTILS 

#include <ostream> 
#include <set> 

template <typename T> 
std::ostream &operator<<(std::ostream &os, const std::set<T> &tgt); 

template <typename T> 
inline std::ostream &operator<<(std::ostream &os, 
           const std::set<T> *tgt) { 
    return os << *tgt; 
} 

#endif 

实现是在utils.cpp

#include "utils.h" 

template <typename T> 
std::ostream &operator<<(std::ostream &os, const std::set<T> &tgt) { 
    os << "{"; 
    bool first = true; 
    for (typename std::set<T>::const_iterator i = tgt.begin(); i != tgt.end(); 
     i++) { 
    if (!first) { 
     os << ", "; 
    } else { 
     first = false; 
    } 
    os << i; 
    } 
    os << "}"; 
    return os; 
} 

我尝试使用它在cout.cpp

#include <iostream> 
#include <set> 
#include "utils.h" 

class Value { 
public: 
    const int value; 
    Value(const int value) : value(value) {} 
}; 

std::ostream &operator<<(std::ostream &os, const Value &tgt) { 
    os << "Value(" << tgt.value << ")"; 
    return os; 
} 

inline std::ostream &operator<<(std::ostream &os, const Value *tgt) { 
    return os << *tgt; 
} 

int main(const int argc, const char **argv) { 
    std::cout << argc << std::endl; 
    std::cout << *argv << std::endl; 
    Value v(10); 
    std::cout << v << std::endl; 
    Value *w = &v; 
    std::cout << *w << std::endl; 
    std::set<const Value *> vs; 
    vs.insert(w); 
    vs.insert(&v); 
    Value x = Value(12); 
    vs.insert(&x); 
    std::cout << vs << std::endl; 
    std::set<const Value *> *p = &vs; 
    std::cout << p << std::endl; 
    return 0; 
} 

我试图编译& ru ñ它具有:

clang++ -c utils.cpp 
clang++ -o cout cout.cpp utils.o 
./cout 

clang++产生的错误是:

tmp/cout-6e3988.o: In function `main': 
cout.cpp:(.text+0x24d): undefined reference to `std::ostream& operator<< <Value const*>(std::ostream&, std::set<Value const*, std::less<Value const*>, std::allocator<Value const*> > const&)' 
/tmp/cout-6e3988.o: In function `std::ostream& operator<< <Value const*>(std::ostream&, std::set<Value const*, std::less<Value const*>, std::allocator<Value const*> > const*)': 
cout.cpp:(.text._ZlsIPK5ValueERSoS3_PKSt3setIT_St4lessIS5_ESaIS5_EE[_ZlsIPK5ValueERSoS3_PKSt3setIT_St4lessIS5_ESaIS5_EE]+0x19): undefined reference to `std::ostream& operator<< <Value const*>(std::ostream&, std::set<Value const*, std::less<Value const*>, std::allocator<Value const*> > const&)' 
clang: error: linker command failed with exit code 1 (use -v to see invocation) 

我明白,它不是在连接过程中找到合适的operator<<实现,但我不知道如何去解决这个问题。

谢谢。

+0

你可能想看看[这里](http://kuhllib.com/2012/01/22/source-organization-of-templates /)。 –

+1

尽管标准C++容器没有输出操作符是令人讨厌的,但定义自己并不是一个好主意:如果你这样做了,其他人也可以这样做,并且最终会违反一个定义规则。另外,如果你定义了一个在任何标准容器上工作的操作符,你需要在名字空间'std'中定义它,只有当它涉及到你定义的东西时才允许使用它。 –

+1

'os << i;'你想输出迭代器吗? :) –

回答

1

您应该在声明它们的头文件中定义模板,以便编译器和链接器可以看到定义。

0

尝试使它const Value* const在你的宣言......

+0

在哪个声明? – oconnor0

+0

@ oconnor0在上面使用'const Value *'的操作符重载中...尝试将其切换到'const Value * const'。 – Mattingly