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

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

新規登録して質問してみよう
ただいま回答率
85.50%
C

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

C++

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

Q&A

解決済

2回答

3681閲覧

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

_pumpkin

総合スコア30

C

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

C++

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

0グッド

0クリップ

投稿2016/12/19 16:11

陶芸家の中三女子に憧れて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];

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

こんにちは。

できれば再現するソースを上げて頂ければよいのですが、上がっているものを使ってやるだけやってみました。
が、結局エラーは取れませんでした。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へ移動しました。

C++

1#include <cstddef> 2namespace wck { 3 template<std::size_t N> 4 class string { 5 private: 6 public: 7 const char text_; 8 const string<N - 1> next_; 9 constexpr string(char const* str) : next_(str + 1) , text_(str[0]){ 10 11 } 12 template<std::size_t V> 13 constexpr char const at(std::size_t pos, string<V> str) const { 14 return pos == 0 ? str.text_ : at(pos - 1, str.next_); 15 } 16 constexpr char const operator[](std::size_t pos) const {//ここです 17 return at(pos,*this); 18 } 19 }; 20 template<> 21 class string<1> { 22 private: 23 public: 24 const char text_; 25 constexpr string(char const* str) : text_(str[0]) { 26 27 } 28 }; 29} 30int main() { 31 constexpr wck::string<3> str1("ab"); 32 33 constexpr char const a = str1[1]; 34}

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

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/20 06:11

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

_pumpkin

2016/12/21 11: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()を特殊化することで分けられました。
guest

0

c++

1namespace wck { 2 template<std::size_t N> 3 class string { 4 private: 5 public: 6 const char text_; 7 const string<N - 1> next_; 8 constexpr string(char* str) : next_(str + 1), text_(str[0]) { 9 10 } 11 template<std::size_t V> 12 constexpr char at(std::size_t pos, string<V> str) { 13 return pos == 0 ? str.text_ : at(pos - 1, str.next_); 14 } 15 constexpr char at(std::size_t pos, char str) { 16 return str; 17 } 18 constexpr char operator[](std::size_t pos) {//ここです 19 return at(pos, *this); 20 } 21 }; 22 template<> 23 class string<1> { 24 public: 25 const char next_; 26 const char text_; 27 constexpr string(char* str) : text_(str[0]),next_(str[0]) { 28 29 } 30 }; 31} 32int main() { 33 constexpr wck::string<13> str1("ab4511gafddf"); 34 constexpr char a = str1[1]; 35}

一応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のコンストラクタに渡す文字数以上になるとエラーとなるようなのでそこの調節も行いました

投稿2016/12/19 19:37

編集2016/12/20 08:44
iwanote

総合スコア295

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問