2016-05-09 49 views
1

我正在編寫一個庫,它應該將對象串聯起來。我選擇支持operator<<(ostream&...重載分辨率和運算符<<模板類型的問題

另一件事是我的圖書館應該提供{?}表格中沒有operator<<(ostream&...的類型的默認字符串化。

問題出在模板類型vector<> - 我不希望用戶爲vector<int>vector<float>寫入2個重載 - 但我無法讓它工作。

下面是代碼:

#include <string> 
#include <type_traits> 
#include <sstream> 
#include <vector> 
#include <iostream> 
using namespace std; 

namespace has_insertion_operator_impl { 
    typedef char no; 
    typedef char yes[2]; 

    struct any_t { 
     template <typename T> 
     any_t(T const&); 
    }; 

    no operator<<(ostream const&, any_t const&); 

    yes& test(ostream&); 
    no test(no); 

    template <typename T> 
    struct has_insertion_operator { 
     static ostream& s; 
     static T const&  t; 
     static bool const value = sizeof(test(s << t)) == sizeof(yes); 
    }; 
} 

template <typename T> 
struct has_insertion_operator : has_insertion_operator_impl::has_insertion_operator<T> {}; 

template <class T> 
typename enable_if<has_insertion_operator<T>::value, string>::type stringify(const T& in) { 
    stringstream stream; 
    stream << in; 
    return stream.str(); 
} 

template <class T> // note the negation here compared to the one above 
typename enable_if< ! has_insertion_operator<T>::value, string>::type stringify(const T&) { 
    return "{?}"; 
} 

// USER CODE: 

struct myType {}; 

ostream& operator<<(ostream& s, const myType&) { s << "myType"; return s; } 

template<typename T> 
ostream& operator<<(ostream& s, const vector<T>&) { s << "vector<T>"; return s; } 

int main() { 
    myType a;   cout << stringify(a) << endl; // prints "myType" 
         cout << stringify(6) << endl; // prints "6" 
    vector<int> v(5); cout << stringify(v) << endl; // prints "{?}" instead of "vector<T>" 

    return 0; 
} 

myType和整數都得到字符串化,但對於vector<int>我得到默認{?}

我需要幫助 - 這對我來說是一個好消息。我需要用戶提供的operator<<(ostream&...重載,而不需要修改即可使用 - 而所有這些都在C++ 98中進行。

+1

_「我的標題不應該拖動任何與他們 - 甚至不是甚至」_雙重:1. [前向聲明](http://stackoverflow.com/questions/625799/resolve-header-include-circular -dependencies-in-c)2. [模板實現](http://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file)。可能這只是一些愚蠢的限制,你能澄清一下爲什麼請推理嗎? –

+0

請提供[mcve]。重視最低限度。你不需要在三個文件中分佈140行代碼來重現你所看到的問題。 – Barry

+1

也絕對傾向於''手動轉發自己聲明所有'std'類型。這是標題存在的目的。 – Barry

回答

0

打開了所有我所要做的就是與插入操作特徵的實施刪除的命名空間所以後備operator<<(ostream&...在全球範圍內結束 - 解釋爲here

1

要匹配你需要爲你的stringize功能

對於C++ 11提供更好的人選載體,這將是:

template <template <typename...> class V, typename... Args> 
typename enable_if< !has_insertion_operator<V<Args...>>::value, string>::type stringify(const V<Args...>&) { 
    return "template {?}"; 
} 
// also add enable_if for yes with code identical to the one in template<typename T> 

由於需要C++ 98,我怕您需要爲1到N(比如5或10)參數提供一些模板重載。喜歡這個。

template <template <typename> class V, typename T0> 
... 
template <template <typename, typename> class V, typename T0, typename T1> 
... 
/// etc 

例如vector你的情況有2個模板參數,並且將匹配第二對yes/no功能