2

実際のより大きなコードを表す次のコードがあります。

#include <iostream>
using namespace std;

template<size_t N> class A {
    public:
        static constexpr size_t getN() {return N;}
};

template<size_t N> class B {
    public:
        void print() { cout << "B created: " << N << '\n';}
};

template <class T> class C {
    public:
        void set(T* a) {
            t_ptr = a;
        }

        void create() {
            constexpr int m = t_ptr->getN();
            B<m> b;
            b.print();
        }

    private:
        T* t_ptr;
};

int main() {
   constexpr int n = 2;
   A<n> a;
   C<A<n> > c;
   c.set(&a);
   c.create();
}

GCC/G++ 4.8.3 でコンパイルするg++ -o main main.cpp -std=c++11と、期待どおりの出力が得られます: B 作成: 2

ただし、GCC/G++ 4.9.1 ではコードがコンパイルされず、次のように出力されます。

main.cpp: In member function ‘void C<T>::create()’:
main.cpp:27:15: error: the value of ‘m’ is not usable in a constant expression
             B<m> b;
               ^
main.cpp:26:27: note: ‘m’ used in its own initializer
             constexpr int m = t_ptr->getN();
                           ^
main.cpp:27:16: error: the value of ‘m’ is not usable in a constant expression
             B<m> b;
                ^
main.cpp:26:27: note: ‘m’ used in its own initializer
             constexpr int m = t_ptr->getN();
                           ^
main.cpp:27:19: error: invalid type in declaration before ‘;’ token
             B<m> b;
                   ^
main.cpp:28:15: error: request for member ‘print’ in ‘b’, which is of non-class type ‘int’
             b.print();
               ^

これは、GCC 4.9 の既知のバグが原因です: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59937およびこの古いスレッドhttps://gcc.gnu.org/ml/gcc-bugs /2013-11/msg00067.htmlの使用がextern回避策として提案されています。ただし、この回避策を機能させることができません。

このコードを GCC 4.9 でコンパイルするのを手伝ってくれませんか? ありがとうございました!

4

1 に答える 1

3

thisではないのでconstexpr、どちらにもアクセスできthis->t_ptrません。

clangのエラーはもう少し役に立ちます

implicit use of 'this' pointer is only allowed within the
    evaluation of a call to a 'constexpr' member function

参照:

N3690 5.19/2 (強調追加)

条件式 e は、e の評価が抽象マシンの規則に従って、次の式のいずれかを評価しない限り、コア定数式です。

これは、e の一部として評価されている constexpr 関数または constexpr コンストラクターを除きます。

タイプ名を介して静的メンバー関数を呼び出すと機能します

constexpr int m = T::getN();
于 2015-01-14T15:19:48.580 に答える