2017-01-13 4 views
1

현재 메타 프로그래밍을 사용하고 있습니다. tmp를 사용하여 유한 상태 시스템을 만들려고합니다. 웹에 몇 가지 구현이 있다는 것을 알고 있지만 연습으로 하나씩 구현하고 싶습니다.C++ 템플릿 메타 프로그래밍 : 오버로드 연산자

저는 기본 클래스 내부에 템플릿 기반 클래스의 템플릿 파생물에 대한 연산자를 오버로드하려고합니다. 그 파생어의

template<typename Input> 
class Base 
{ 
public: 
    virtual ~Base() = default;  
    virtual bool operator()(const Input& input) const = 0; 

    template<typename Lhs, typename Rhs> 
    constexpr Derivation1<Input, Lhs, Rhs> operator||(const Lhs& left, const Rhs& right) const; 

    template<typename Lhs, typename Rhs> 
    constexpr Derivation2<Input, Lhs, Rhs> operator&&(const Lhs& left, const Rhs& right) const; 
}; 

2 :

template<typename Input, typename... TSpecialized> 
class Derivation1 : public Base<Input> 
{ 
public: 
    bool operator()(const Input& input) const override 
    { 
     // ... 
    } 
}; 

template<typename Input, typename... TSpecialized> 
class Derivation2 : public Base<Input> 
{ 
public: 
    bool operator()(const Input& input) const override 
    { 
     // ... 
    } 
}; 

우리는 기본 클래스에 선언 된 사업자의 정의 :

template <typename Input> 
template <typename Lhs, typename Rhs> 
constexpr Derivation1<Input, Lhs, Rhs> Base<Input>::operator||(const Lhs& left, const Rhs& right) const 
{ 
    return Derivation1<Input, Lhs, Rhs>(); 
} 

template <typename Input> 
template <typename Lhs, typename Rhs> 
constexpr Derivation2<Input, Lhs, Rhs> Base<Input>::operator&&(const Lhs& left, const Rhs& right) const 
{ 
    return Derivation2<Input, Lhs, Rhs>(); 
} 

유형 우리는 기본 클래스가 있다고 가정 Rhs와 Lhs는 기본 클래스의 파생어입니다.

내가 좋아하는 연산자를 사용하려고

:

Derivation3<int, 10, 20> left; 
Derivation4<int, 300, 290> right; 

auto result = left || right; 

나는 연산자의 오버로드가 인수 일치하지 않습니다라는 오류를 받고 있어요. 두 파생어의 기본 유형은 동일합니다 (Base<int>). 오버로드를 선언해야합니다. 변수 resultDerivation1이어야합니다 (위 코드에서 선언 한 것과 같습니다).

이 경우 어떻게하면 운영 체제를 제대로 오버로드 할 수 있습니까?

+0

감사합니다. 조건은 자료를 의미하는 오타입니다. 파생 클래스 3과 4는 기본 클래스의 다른 파생 클래스를 나타 내기 때문에 정확합니다. Derivation1과 Derivation2는 논리적 인 and와 and를 구현하기 때문에 특별한 경우이다. 그렇기 때문에 이들 연산자에 의해 반환됩니다. – Timo

답변

3

해결책을 찾았습니다. 나는 기본 클래스의 형식 정의를 만들었습니다

template<typename Input> 
class Base 
{ 
public: 
    virtual ~Base() = default;  
    virtual bool operator()(const Input& input) const = 0; 

    typedef Input inputType; 
}; 

나는 클래스의 외부에 과부하 운영자 이동 : 의도 한대로

template <typename Lhs, typename Rhs> 
constexpr Derivation1<typename Lhs::inputType, Lhs, Rhs> operator||(const Lhs& left, const Rhs& right) 
{ 
    return Derivation1<typename Lhs::inputType, Lhs, Rhs>(); 
} 

template <typename Lhs, typename Rhs> 
constexpr Derivation2<typename Lhs::inputType, Lhs, Rhs> operator&&(const Lhs& left, const Rhs& right) 
{ 
    return Derivation2<typename Lhs::inputType, Lhs, Rhs>(); 
} 

이 코드는 완벽하게 작동합니다.

+0

컴파일러가'Base'에서 함수를 선언 할 수 있다면 놀랍습니다. 거기에는 친구 지정자가 필요했습니다. – Potatoswatter