質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.48%

  • C

    4641questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

  • C++

    4504questions

    C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

コンパイル時文字列の実装でエラー[C/C++]

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 1,552

_pumpkin

score 22

陶芸家の中三女子に憧れてconstexpr stringを実装しようと試みたのですが、早速添え字演算子でエラーがでてしまいました。どうすればいいのか、なぜそうなるのか教えてくださると有難いです。

namespace wck {
    template<std::size_t N>
    class string {
    private:
    public:
        const char text_;
        const string<N - 1> next_;
        constexpr string(char* str) : next_(str + 1) , text_(str[0]){

        }
        template<std::size_t V>
        constexpr char at(std::size_t pos, string<V> str) {
            return pos == 0 ? str.text_ : at(pos - 1, str.next_);
        }
        constexpr char operator[](std::size_t pos){//ここです
            return at(pos,*this);
        }
    };
    template<>
    class string<1> {
    private:
        const char text_;
    public:
        constexpr string(char* str) : text_(str[0]) {

        }
    };
}
int main() {
    constexpr wck::string<3> str1("ab");

    constexpr char a = str1[1];
}


こんなエラーです(gcc)
prog.cc: In function 'int main()':
prog.cc:32:15: error: 'wck' does not name a type
constexpr wck::string<3> str1("ab");
^~~
prog.cc:34:24: error: 'str1' was not declared in this scope
constexpr char a = str1[1];
^~~~
prog.cc:34:20: warning: unused variable 'a' [-Wunused-variable]
constexpr char a = str1[1];

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+1

こんにちは。

できれば再現するソースを上げて頂ければよいのですが、上がっているものを使ってやるだけやってみました。
が、結局エラーは取れませんでした。msvc 2015では通るのですが、MinGW(gcc) 5.4.0では通りません。
(取り敢えず、-std=c++14をつけてます。gccのバージョンやオプョンも情報公開された方が話は早いと思いますよ。)

まず、そのままですとstd::size_t未定義ですので、#include <cstddef>を補いました。
次に、const指定漏れが多数ありましたので、補いました。
最初に"ab"という、char const[3]型を与えているため、以降、全てconstが必要になります。
途中非const変数へconst変数を代入しようとしてエラーになります。
そして、class string<1>のtext_をプライマリのstring<>からアクセスしようとしてprivateエラーとなりましたので、publicへ移動しました。

#include <cstddef>
namespace wck {
    template<std::size_t N>
    class string {
    private:
    public:
        const char text_;
        const string<N - 1> next_;
        constexpr string(char const* str) : next_(str + 1) , text_(str[0]){

        }
        template<std::size_t V>
        constexpr char const at(std::size_t pos, string<V> str) const {
            return pos == 0 ? str.text_ : at(pos - 1, str.next_);
        }
        constexpr char const operator[](std::size_t pos) const {//ここです
            return at(pos,*this);
        }
    };
    template<>
    class string<1> {
    private:
    public:
        const char text_;
        constexpr string(char const* str) : text_(str[0]) {

        }
    };
}
int main() {
    constexpr wck::string<3> str1("ab");

    constexpr char const a = str1[1];
}

最後に残ったエラーは、下記です。

test.cpp: In instantiation of 'constexpr const char wck::string<N>::at(std::size_t, wck::string<V>) const [with unsigned int V = 1u; unsigned int N = 3u; std::size_t = unsigned int]':
test.cpp:14:45:   recursively required from 'constexpr const char wck::string<N>::at(std::size_t, wck::string<V>) const [with unsigned int V = 2u; unsigned int N = 3u; std::size_t = unsigned int]'
test.cpp:14:45:   required from 'constexpr const char wck::string<N>::at(std::size_t, wck::string<V>) const [with unsigned int V = 3u; unsigned int N = 3u; std::size_t = unsigned int]'
test.cpp:17:22:   required from 'constexpr const char wck::string<N>::operator[](std::size_t) const [with unsigned int N = 3u; std::size_t = unsigned int]'
test.cpp:33:36:   required from here
test.cpp:14:45: error: 'class wck::string<1u>' has no member named 'next_'
             return pos == 0 ? str.text_ : at(pos - 1, str.next_);
                                             ^

constexpr char const a = str1[1];でoperator[]が呼ばれ、それがat(1, str1)を呼ぶことになります。
そのat()は、at(0, string<2>::next_)を呼びます。そのat()はat(-1, string<1>::next_)を呼びませんが、評価はされますので、string<1>::next_はないから、未定義エラーになります。
msvcは呼ばれない場合は評価しないのかも知れません。(バグの検出が遅れるため、嫌な仕様です。)

この問題は_pumpkinさんのところでは発生していないようですので、対策は省略します。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/12/21 20:34

    ```
    #include<iostream>

    namespace wck {
    template<std::size_t L>
    class string {
    private:
    public:
    char str_;
    string<L - 1> next_;
    constexpr string(const char* str) : str_(*str), next_(str + 1) {

    }
    constexpr char operator[](size_t pos) const{
    return advance(*this, pos);
    }
    };
    template<>
    class string<1> {
    private:
    public:
    char str_ = '\0';
    constexpr string(const char*) {

    }
    };
    template<std::size_t N>
    constexpr char advance(string<N> str, std::size_t pos) {
    return pos == 0 ? str.str_ : advance(str.next_, pos - 1);
    }
    template<>
    constexpr char advance<1>(string<1> str, std::size_t) {
    return str.str_;
    }
    }

    int main() {
    constexpr wck::string<3> str("ab");
    constexpr char result = str[0];
    std::cout << result << std::endl;
    return 0;
    }
    ```
    結果、このようにして実現しました。
    wck::string.at()は、stdの方と引数が違うため、advance()というグローバル関数を作りました。
    wck::string<1>のときにnext_メンバがない問題は、advance()を特殊化することで分けられました。

    キャンセル

+1

namespace wck {
    template<std::size_t N>
    class string {
    private:
    public:
        const char text_;
        const string<N - 1> next_;
        constexpr string(char* str) : next_(str + 1), text_(str[0]) {

        }
        template<std::size_t V>
        constexpr char at(std::size_t pos, string<V> str) {
            return pos == 0 ? str.text_ : at(pos - 1, str.next_);
        }
        constexpr char at(std::size_t pos, char str) {
            return str;
        }
        constexpr char operator[](std::size_t pos) {//ここです
            return at(pos, *this);
        }
    };
    template<>
    class string<1> {
    public:
        const char next_;
        const char text_;
        constexpr string(char* str) : text_(str[0]),next_(str[0]) {

        }
    };
}
int main() {
    constexpr wck::string<13> str1("ab4511gafddf");
    constexpr char a = str1[1];
}


一応VisualStudio2015環境においてこちらのプログラムで実行できました。
string<1>にchar型のnext_変数を与え、at(std::size_t, char str)とオーバーロードすることにより、atメゾッドのエラーをなくしました。正しい方法かはわかりません。
また、string<1>でprivateになっていてエラーが出ていたtext_をpublicに変更しました。
起こったというエラーは再現しなかったのでよくわからなかったです…

追記
iostreamをincludeし、確認用にstd::coutをmainに加えたのちMinGWを使用し、
g++にてコンパイルをしたところ通りました。-std=c++11を指定しました。
main内のstring<>の数値がstr1のコンストラクタに渡す文字数以上になるとエラーとなるようなのでそこの調節も行いました

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

同じタグがついた質問を見る

  • C

    4641questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

  • C++

    4504questions

    C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。