2013-05-22 64 views
1

我有以下情況。我有一個類foo我自己的命名空間內my_lib來自不同命名空間的朋友方法

namespace my_lib{ 

template<typename T> 
class foo{ 
    T data; 
public: 
    // blah blah 
}; 

} 

我想接口,可以有自己的命名空間other_lib另一個庫。我將這個接口放在我自己的my_libwrapper命名空間中。具體來說,我的複製方法my_lib::wrapper::copy我需要訪問my_lib::foo::data,所以我需要實現以下幾點:

namespace my_lib{ 
namespace wrapper{ 

template<typename T> 
void copy(const foo<T>& my_foo, other_lib::foo<T>& other_foo) 
{ 
    // copy my_foo.data to other_foo 
} 

} 
} 

做到這一點my_lib::wrapper::copy方法必須my_lib::foo類的朋友。我可以通過一系列的前置聲明中foo.h

// forward declare other_lib::foo 
namespace other_lib{ 
template<typename T> 
class foo; 
} 

namespace my_lib{ 

// forward declare wrapper::copy 
namespace wrapper{ 
template<typename T> 
void copy(const foo<T>& my_foo, other_lib::foo<T>& other_foo); 
} 

template<typename T> 
class foo{ 
    T data; 

    friend void copy(const foo<T>& my_foo, other_lib::foo<T>& other_foo); 
public: 
    // blah blah 
}; 

} 

這個作品做到這一點,但我不喜歡它。一方面,它將很多東西添加到與other_libwrapper名稱空間無關的文件中。此外,在我的代碼中使用其他庫是可選的,但如果有人包括foo.h他們將看到各種無關的前向聲明,並開始想知道爲什麼...

我該如何解決這個設計?

+0

爲什麼不提供對'foo'的迭代器訪問,以便您不需要任何朋友函數? – TemplateRex

+0

@rhalbersma我其實就是這麼想的。原因有兩個:1)用戶確實/不應該真的需要任何形式的內部數據訪問2)這個類的迭代器有點麻煩和不平凡(foo是CRS稀疏矩陣格式的實現)......但是我想我可以,如果這是做這件事的唯一方式 – GradGuy

+0

如果需要在某些完全不相關的命名空間「friend」訪問中授予'copy'函數,那麼'foo'的接口根本就不完整。你應該把'copy'放在'foo'裏面(以及其他所有'foo'用戶需要的算法),或者提供一組最小的數據訪問成員函數(最好是迭代器,而不是原始數據的句柄),以便其他類可以實現在'foo'上運行的算法。 – TemplateRex

回答

2

句法技巧讓friend在其他名稱空間上工作,正確的方法是修復您的設計。如果需要在某些完全不相關的命名空間朋友訪問中授予copy()函數,則foo的界面爲simply not complete

一種方法是將copy()放入foo(以及foo用戶需要的任何其他算法)中。如果做得對,這會產生一個完整可用的類foo。例如。看看std::list,它有自己的sort()成員函數來利用列表實現細節。但是,這可能會很快導致foo臃腫的類接口(請查看std::string),因此不推薦將其作爲一般規則。

或者,您可以提供一組最小的數據訪問成員函數(最好是迭代器,而不是原始數據的句柄),以便其他類可以實現在foo上運行的算法。在foo內使用常規容器(數組,矢量等)作爲數據表示,這將是我對一般用途的建議。

但是,由於您的類foo有一個棘手的稀疏矩陣表示,您應該首先嚐試算法 - 成員 - 方法。

相關問題