C++:error C2228: left of '.str' must have class/struct/union
阿新 • • 發佈:2018-10-31
如下程式碼報error C2228: left of '.str' must have class/struct/union
#include <string> #include <iostream> #include <vector> using namespace std; template <typename T> class ValueBox { private: T value; private: template<typename U, typename std::enable_if<std::is_class<U>::value && !std::is_same<U, string>::value, U>::type* = nullptr, typename std::enable_if<!class_str<U>::ret, U>::type* = nullptr> std::string str(const T&) { cout << "1.---------------------" << endl; return "null"; }; template<typename U, typename std::enable_if<std::is_class<U>::value && std::is_same<U, string>::value, U>::type* = nullptr> std::string str(const T&) { cout << "2.---------------------" << endl; return value; }; template<typename U, typename std::enable_if<std::is_class<U>::value && !std::is_same<U, string>::value, U>::type* = nullptr, typename std::enable_if<class_str<U>::ret, U>::type* = nullptr> std::string str(const T&) { cout << "3.---------------------" << endl; return value.str(); }; template<typename U, typename std::enable_if<!std::is_class<U>::value && std::is_arithmetic<U>::value, U>::type* = nullptr> std::string str(const T&) { cout << "4.---------------------" << endl; return std::to_string(value); }; public: ValueBox(const T& _value) : value(_value) { } const T& getValue() const { return value; }; T& getValue() { return value; }; std::string str() { return str<T>(value); }; }; int main() { ValueBox<string> s("sddds"); cout << s.str() << endl; ValueBox<bool> j ( true); cout << j.str() << endl; ValueBox<int> i(100); cout << i.str() << endl; ValueBox<float> f ( 10.6f); cout << f.str() << endl; ValueBox<Box> b1 (Box()); cout << b1.str() << endl; ValueBox<Bin> b2 (Bin()); cout << b2.str() << endl; return 1; }
報錯的原因是C++ 編譯器把ValueBox<Box> b1 (Box());中的b1看成的函式定義,把Box()看成是返回值為Box的無引數函式,只不過此時的引數名稱未定義罷了。這種錯誤有一個通用的名稱,叫做:Most Vexing Parse
修改的方法有如下幾種:
1、將Box單獨放一行並初始化
Box b; // 不能使用Box b();,這樣b又會被當成函式定義了
ValueBox<Box> b1 (b);
2、將Box()用括號包起來,這樣Box()就不會被看成是函數了
ValueBox<Box> b1 ((Box()));
3、使用C++1中的統一初始化語法,即使用{}
ValueBox<Box> b1 {Box()};
參考文件
C++語法分析中最讓人頭疼的歧義
Item 6. Be alert for C++'s most vexing parse
Effective STL 筆記: Item 6--Be alert for C++'s most vexing parse