2012-10-24 70 views
3

我有一些理解MPL佔位符的麻煩。
有人請解釋我爲什麼這段代碼無法編譯?默認模板參數MPL佔位符替換

我期望打印數字0,1 & 2,但當編譯器試圖確定Wrapper的默認模板參數的類型時,似乎佔位符不會被實際類型替換。

#include <iostream> 
#include <boost/mpl/inherit.hpp> 
#include <boost/mpl/inherit_linearly.hpp> 
#include <boost/mpl/int.hpp> 
#include <boost/mpl/vector.hpp> 

template <typename T> struct Traits; 

template<> struct Traits<int> { typedef boost::mpl::int_<0> type; }; 
template<> struct Traits<char> { typedef boost::mpl::int_<1> type; }; 
template<> struct Traits<bool> { typedef boost::mpl::int_<2> type; }; 

template <typename T, typename Type=typename Traits<T>::type > struct Wrapper 
{ 
    Wrapper() { std::cout << "Value: " << Type::value << std::endl; } 

    T value; 
}; 

int main() 
{ 
    typedef boost::mpl::inherit_linearly< 
       boost::mpl::vector<int, char, bool>, 
       boost::mpl::inherit<boost::mpl::_1, Wrapper<boost::mpl::_2> > >::type Object; 

    Object obj; 

    return 0; 
} 

這是從GCC-4.1.2的錯誤(我知道...舊的編譯器在工作)

# g++4 -I ../boost test.cpp -o test 
test.cpp: In function 'int main()': 
test.cpp:24: error: invalid use of undefined type 'struct Traits<mpl_::arg<2> >' 
test.cpp:7: error: declaration of 'struct Traits<mpl_::arg<2> >' 
test.cpp:24: error: template argument 2 is invalid 
test.cpp:24: error: template argument 2 is invalid 
test.cpp:24: error: template argument 2 is invalid 
test.cpp:24: error: expected initializer before 'Object' 
test.cpp:26: error: 'Object' was not declared in this scope 
test.cpp:26: error: expected `;' before 'obj' 

編輯: Acorbe的answer以下後,我做了一個變體我的示例程序中顯示爲什麼他提出的解決方案不符合我的需求。這說明了我在做什麼。在這種情況下,我希望打印文本TYPE_A,TYPE_B,TYPE_A。 g ++錯誤是一樣的。

#include <iostream> 
#include <boost/mpl/inherit.hpp> 
#include <boost/mpl/inherit_linearly.hpp> 
#include <boost/mpl/int.hpp> 
#include <boost/mpl/vector.hpp> 

enum WrapperType { TYPE_A, TYPE_B }; 

template <typename T> struct Traits; 

template<> struct Traits<int> { typedef boost::mpl::int_<TYPE_A> type; }; 
template<> struct Traits<char> { typedef boost::mpl::int_<TYPE_B> type; }; 
template<> struct Traits<bool> { typedef boost::mpl::int_<TYPE_A> type; }; 

template <typename T, typename Type=typename Traits<T>::type > struct Wrapper; 

template <typename T> 
struct Wrapper<T, boost::mpl::int_<TYPE_A> > 
{ 
    Wrapper() : value (0) { std::cout << "TYPE_A" << std::endl; } 

    T value; 
}; 

template <typename T> 
struct Wrapper<T, boost::mpl::int_<TYPE_B> > 
{ 
    Wrapper() { std::cout << "TYPE_B" << std::endl; } 

    T value; 
}; 

int main() 
{ 
    typedef boost::mpl::inherit_linearly< 
       boost::mpl::vector<int, char, bool>, 
       boost::mpl::inherit<boost::mpl::_1, Wrapper<boost::mpl::_2> > >::type Object; 

    Object obj; 

    return 0; 
} 

這是從GCC-4.5.4

# g++ -I ../boost test.cpp -o test 
test.cpp: In functie ‘int main()’: 
test.cpp:37:79: fout: invalid use of incomplete type ‘struct Traits<mpl_::arg<2> >’ 
test.cpp:9:34: fout: declaration of ‘struct Traits<mpl_::arg<2> >’ 
test.cpp:37:79: fout: template argument 2 is invalid 
test.cpp:37:81: fout: template argument 2 is invalid 
test.cpp:37:83: fout: template argument 2 is invalid 
test.cpp:37:91: fout: expected initializer before ‘Object’ 
test.cpp:39:9: fout: ‘Object’ was not declared in this scope 
test.cpp:39:16: fout: expected ‘;’ before ‘obj’ 

這是(部分)從鐺++錯誤的錯誤 - 3.1:

test.cpp:15:50: error: implicit instantiation of undefined template 'Traits<mpl_::arg<2> >' 
    template <typename T, typename Type=typename Traits<T>::type > struct Wrapper; 
               ^
test.cpp:37:57: note: in instantiation of default argument for 'Wrapper<mpl_::arg<2> >' required here 
        boost::mpl::inherit<boost::mpl::_1, Wrapper<boost::mpl::_2> > >::type Object; 
                 ^~~~~~~~~~~~~~~~~~~~~~~ 
test.cpp:9:34: note: template is declared here 
    template <typename T> struct Traits; 
+0

對於它的價值,我有2點建議:1。你沒有忘記做的'類型定義typename'而不僅僅是'typename'? 2.在'Wrapper'構造函數聲明中不需要''。 – Acorbe

+0

@Acorbe:只有從屬名稱需要''typename',這裏不是這種情況。然而第二點是有效的,在構造函數IIRC中說''實際上是一個錯誤。 – Xeo

+0

@Acorbe @Xeo:謝謝你的回覆。我不知道''是無效的。我已經從構造函數聲明中刪除它,這已經減少了一些錯誤。未定義類型的'無效使用'結構特性>''仍然不幸。 – CodeWarrior

回答

1

好吧......我似乎已經破解了它......
往往,一個額外的抽象層次伎倆。

我創建了一個元函數類(genWrapper),它與佔位符一起傳遞給mpl :: apply1。那裏的元函數會返回預期的包裝類型。

這裏是結果程序(第2版)。
感謝大家的幫助和指示。

#include <iostream> 
#include <boost/mpl/apply.hpp> 
#include <boost/mpl/inherit.hpp> 
#include <boost/mpl/inherit_linearly.hpp> 
#include <boost/mpl/int.hpp> 
#include <boost/mpl/vector.hpp> 

enum WrapperType { TYPE_A, TYPE_B }; 

template <typename T> struct Traits; 

template<> struct Traits<int> { typedef boost::mpl::int_<TYPE_A> type; }; 
template<> struct Traits<char> { typedef boost::mpl::int_<TYPE_B> type; }; 
template<> struct Traits<bool> { typedef boost::mpl::int_<TYPE_A> type; }; 

template <typename T, typename Type = typename Traits<T>::type> struct Wrapper; 

template <typename T> 
struct Wrapper<T, boost::mpl::int_<TYPE_A> > 
{ 
    Wrapper() : value (0) { std::cout << "TYPE_A" << std::endl; } 

    T value; 
}; 

template <typename T> 
struct Wrapper<T, boost::mpl::int_<TYPE_B> > 
{ 
    Wrapper() { std::cout << "TYPE_B" << std::endl; } 

    T value; 
}; 

struct genWrapper 
{ 
    template <typename T> 
    struct apply 
    { 
     typedef Wrapper<T> type; 
    }; 
}; 

int main() 
{ 
    typedef boost::mpl::inherit_linearly< 
       boost::mpl::vector<int, char, bool>, 
       boost::mpl::inherit<boost::mpl::_1, boost::mpl::apply1<genWrapper, boost::mpl::_2> > >::type Object; 

    Object obj; 

    return 0; 
} 

這是輸出結果:

# g++4 -I ../boost test.cpp -o test 
# ./test 
TYPE_A 
TYPE_B 
TYPE_A 
1

我做了一個小的變化代碼分裂由兩個更簡單的typedef s中的默認模板參數引起的typedef

考慮一下:

template < typename T , typename Super_Type = Traits<T> > struct Wrapper 
{ 
    typedef typename Super_Type::type Type; 
    Wrapper() { std::cout << "Value: " << Type::value << std::endl; } 

    T value; 
}; 

這樣它編譯。我的懷疑是你的原始表達(儘管正確)是某種程度上太複雜,不能被編譯器正確擴展。

+0

謝謝!這確實編譯得很好,但它不符合我想要做的。我想能夠部分專門化第二個模板參數中的Wrapper。看起來我太簡化了我的例子。我會更新我原來的帖子,以顯示我的後...我試圖用g ++ - 4.5.4和clang ++ - 3.1來編譯,並得到類似的錯誤消息。我不認爲代碼對於編譯器來說太複雜,但更多的是我沒有掌握MPL佔位符的複雜性。 – CodeWarrior

+0

現在考慮到現在你已經很重要,正在改變你的問題。請將您的新代碼寫入一個新問題,或者至少在「編輯」部分。否則,你的行爲對那些自願閱讀並處理你的代碼的人來說會顯得很不尊重。這不是它的工作方式! – Acorbe

+0

考慮這個meta.stackoverflow.com/questions/2081/solve-the-modified-question-problem – Acorbe