2017-07-10 8 views
1

はここで簡単なconstexprのリンクリストの作成での私の試みだ - このプログラムをコンパイルするにconstexprのリンクリスト - Xへのconst Xの*から無効な変換*

struct Node 
{ 
    constexpr Node(const int n, Node const* next = nullptr) 
     : value(n), next(next) {} 
    constexpr Node push(const int n) const { return Node(n, this); } 

    int value; 
    Node const* next; 
}; 

constexpr auto getSum(Node n) { 
    int sum = 0; 
    Node *current = &n; 
    while(current != nullptr) { 
     sum += current->value; 
     current = current->next; 
    } 
    return sum; 
} 

int main() { 
    constexpr Node a(0); 
    a.push(1); 
    a.push(22); 
    constexpr auto result = getSum(a); 
    return result; 
} 

を、次のエラーが

prog.cc: In function 'constexpr auto getSum(Node)': 
prog.cc:16:28: error: invalid conversion from 'const Node*' to 'Node*' [-fpermissive] 
     current = current->next; 
        ~~~~~~~~~^~~~ 
prog.cc: In function 'int main()': 
prog.cc:25:35: in constexpr expansion of 'getSum(a)' 
prog.cc:16:28: error: conversion of 'const Node*' null pointer to 'Node*' is not a constant expression 
を示しています

この問題を解決し、そのようなリンクリストを生成するにはどうすればよいですか?実行をオンラインで確認するためのWandbox Linkがあります。

+0

うわー、私は何をやっているその可能性を考えていない... –

+1

'constexpr'オブジェクトまだ抽象機械の規則に従ってください。 'push'へのすべての呼び出しは即時に終了する一時的なものを返します。エラーを修正した場合でも、リストは決して拡大しません。 – StoryTeller

+3

ダン..私が今まで見た中で最もconstとconstexprでなければなりません。 – Brandon

答えて

4

即時エラーが修正するのは簡単です:

Node const *current = &n; 
    // ^^^^^ 

苦情がcurrent = current->next;Node const*Node *に割り当てているので、それをしないということです。

これを実行すると、pushも変更されていないので、プログラムはコンパイルされますが、0が印刷されます。a。自動ローカル変数であるaのアドレスは定数式ではないため、pushの結果をconstexprとして保存することはできません。

あなたは、しかし、一時的なノードのリンクリストを形成し、それをすぐに使用することができます。

constexpr auto result = getSum(a.push(1).push(22).push(19)); // OK, 42 
1

@hg_gitさんが投稿の解説で指摘したように、constexprリンクリストは使用できません。

コードをクリーンアップして便利なエラーが発生しました。

キーワード constが存在しない場合であっても、見ることができるように、constのパラメータを持ついくつかの問題がまだある。この

main.cpp: In function 'int main()': 
main.cpp:25:13: error: passing 'const Node' as 'this' argument discards qualifiers [-fpermissive] 
    a.push(1); 
      ^
main.cpp:7:20: note: in call to 'constexpr Node Node::push(int)' 
    constexpr Node push(const int n) { return Node(n, this); } 
        ^~~~ 
main.cpp:26:14: error: passing 'const Node' as 'this' argument discards qualifiers [-fpermissive] 
    a.push(22); 
      ^
main.cpp:7:20: note: in call to 'constexpr Node Node::push(int)' 
    constexpr Node push(const int n) { return Node(n, this); } 

を与える

#include <iostream> 

struct Node 
{ 
    constexpr Node(const int n, Node * next = nullptr) 
     : value(n), next(next) {} 
    constexpr Node push(const int n) { return Node(n, this); } 

    int value; 
    Node * next; 
}; 

constexpr auto getSum(Node n) { 
    int sum = 0; 
    Node *current = &n; 
    while(current != nullptr) { 
     sum += current->value; 
     current = current->next; 
    } 
    return sum; 
} 

int main() { 
    constexpr Node a(0); 
    a.push(1); 
    a.push(22); 
    constexpr auto result = getSum(a); 
    return result; 
} 

。これは、コンパイル時にconstexprが計算されるためです。したがって実行時に不変にします。

リンクリストは実行時に変更される可能性があります。例ごとにノードを追加または削除する場合 だから、constexprはこの場合正しい選択ではありません。

編集: コードのlive demoは、constexprからきれいです。私はいくつかの解説を加え、あなたがラインや機能を理解していないかどうか尋ねてみてください。

+0

それは可能です、私たちはただの一時的なオブジェクトの生涯を世話する必要があります:) –

関連する問題