C++:error C2228: left of '.str' must have class/struct/union

如下代码报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

猜你喜欢

转载自blog.csdn.net/netyeaxi/article/details/83507855