템플릿 메타 프로그래밍

누군가 첫 번째 템플릿 메타 프로그래밍 방식이 무한 루프가되는 이유를 설명해 줄 수 있지만 두 번째 템플릿은 올바르게 실행됩니다.

#include <iostream>
using namespace std;

template<int N, int M>
struct commondivs {                                              
  static const int val = (N<M) ? commondivs<N,(M-N)>::val : commondivs<(N-M),M>::val;
};

template<int N>
struct commondivs<N,N> {
  static const int val = N;
};


int commondiv(int N, int M){
    if(N==M){
        return N;
    }   
    return (N<M)?commondiv(N,(M-N)):commondiv((N-M),M);     
}

int main() {

    cout << commondivs<9,6>::val << endl;
    cout << commondiv(9,6) << endl;
    return 0;
}



답변

(N<M) ? commondivs<N,(M-N)>::val : commondivs<(N-M),M>::val

이 라인은 컴파일 타임에 조건이 알려져 있고 브랜치 중 하나가 절대 사용되지 않더라도 commondivs<N,(M-N)>::val및의 인스턴스를 생성 commondivs<(N-M),M>::val합니다.

교체 ? :std::conditional_t이러한 제한이 없습니다있는 :

static const int val = std::conditional_t<N < M, commondivs<N,(M-N)>, commondivs<(N-M),M>>::val;


답변

문제는 조건 연산자의 모든 피연산자가 평가 모두 있도록 할 것입니다 commondivs<N,(M-N)>commondivs<(N-M),M>인스턴스화과 취득 val후 재귀 템플릿 인스턴스화에 리드를 GET 평가합니다.

constexpr 을 적용 하고 constexpr static멤버 함수 에 넣을 수 있습니다 .

값이 true이면 statement-false가 삭제되고 (있는 경우), 그렇지 않으면 statement-true가 삭제됩니다.

template<int N, int M>
struct commondivs {                                              
  constexpr static int get_val() {
    if constexpr (N<M) return commondivs<N,(M-N)>::val; // if true, the else part won't be evaluated
    else return commondivs<(N-M),M>::val;               // vice versa
  }
  static const int val = get_val();
};

라이브


답변

삼항 연산자는 다릅니다 if constexpr: 컴파일러가 그것을 볼 때 두 가지 모두에 대한 코드를 생성해야합니다. 즉, 템플릿을 인스턴스화하기 commondivs<M, N>위해 컴파일러 템플릿 commondivs<N, M - N>과를 모두 인스턴스화 합니다commondivs<N - M, M> .

그와 대조적으로, commondiv(N, M - N)그리고 commondiv(N - M, M)두 개의 함수 호출로 변환한다. 어떤 것이 취해 졌는지, 실제로 함수가 호출 될 때 결정됩니다.

부가.

HolyBlackCat 는로 솔루션을 제공했습니다 std::conditional_t. 다른 하나는 다음과 같습니다.

template<int N, int M>
struct commondivs {                                              
    static constexpr int min = (N < M) ? N : M;
    static constexpr int max = (N < M) ? M : N;
    static constexpr int val = commondivs<min, max - min>::val;
};

template<int N>
struct commondivs<N, N> {
    static constexpr int val = N;
};


답변

다음과 같은 이유로 무한 재귀가 발생합니다.

static const int val = (N<M) ? commondivs<N,(M-N)>::val : commondivs<(N-M),M>::val;

?:@Eng가 말했듯이,가 아니기 때문에 프로그래밍을 전혀 템플릿하지 않습니다 constexpr.

@HolyBlackCat의 답변을보고 싶습니다.


답변