1. ホーム
  2. C++

C++: エラー C2228: '.str' の左側にはクラス/構造体/結合が必要

2022-02-09 14:06:35

次のコードはエラー 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()); を関数定義と見なし、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++11の統一的な初期化構文で、{}を使用する。
ValueBox<Box> b1 {Box()} です。

参考資料
C++の構文解析で最も頭痛の種となる曖昧さ
項目6.C++の最も厄介な構文解析を警戒せよ
Effective STLノート。項目6--C++の最も厄介な構文解析に注意する