2017-05-06 6 views
1

, 나는 다음과 같은 다른 차원의 시스템에 대처하기 위해 템플릿 클래스를 정의 시스템의 크기. 뭐 그런 : 자동 생성 기능 헤더, 내가 문제가 가변 인자 템플릿

Out-of-line definition of 'fun' does not match any declaration in 'system<3>' 

이 또한 내가 헤더 기능이 자동 생성 템플릿 매개 변수 N에 따라 될 것이라고 싶습니다
template <> 
template<typename T> 
void system<1>::fun(T & a){ } 

template <> 
template<typename T> 
void system<2>::fun(T & a, T & b){ } 

template <> 
template<typename T> 
void system<3>::fun(T & a, T & b, T & c){ } 

그러나하려 컴파일러는 다음과 같은 오류를 제공이 전략을 사용합니다. 나는 variadic 템플릿을 사용하려했지만 행운이 없었다.

+1

저는 100 % 확신하지 못하고 있지만이 방법은 잘못된 것 같습니다. 코드를 자동 생성하는 데 뭔가 다른 방법을 사용하는 것이 더 나을 것입니다 (예 : 작은 스크립트) – UnholySheep

답변

1

N을 기반으로 자동 생성이 가능하다면, 일반적으로 필요한 것을 수행 할 수있는 코드를 작성할 수 있다고 생각합니다. (variadics를 사용하려고 시도한 의견은이를 강화합니다).

귀하의 기능이 또한 T에 템플릿 화되어 있다는 사실은 안타깝게도 제가 바라는 것보다 조금 더 복잡합니다. 필자가 제공하는 것보다 간단한 솔루션이 있지만 필자가 보았던 유일한 유형은 유형을 명시 적으로 지정하거나 컴파일 타임에 수행 할 수있는 런타임 검사를 미루는 것입니다. 그대로, 내가 원하는대로 할 수있는 유일한 방법은 가변성 템플릿을 사용하는 것입니다. 이것은 당신이 원하는의 대부분을 가져옵니다

template <std::size_t N> 
class System { 

    template <class ... Ts> 
    void fun(Ts& ts) { 
     static_assert(sizeof...(Ts) == N, "Wrong number of parameters!");  
    } 
}; 

나는 그것이 차이를 만들 것입니다 가능성은 거의이기 때문에 당신이라는 이름의 또 다른 멤버 함수를 가질 계획이 아니라면 그것을 경우, 수 일을 간단하게 유지하기 위해 (그리고보다는 정적 주장했습니다 fun ... 그렇게하지 마세요). 이제이 함수는 N 개의 인수로 호출되는 것을 허용하지만 모든 유형이 다를 수 있습니다. 당신은 그들 모두가 같기를 원합니다. 그래서 우리는 약간의 TMP가 필요합니다.

template <class ... Ts> 
struct all_same{}; 

template <class T> 
struct all_same<T> : std::true_type { 
    using same_type = T;  
}; 

template <class T, class ... Ts> 
struct all_same<T, T, Ts...> : all_same<T, Ts...> {}; 

template <class T1, class T2, class ... Ts> 
struct all_same<T1, T2, Ts...> : std::false_type {}; 

일부 재귀 적 TMP는 우리가 원하는 것을 얻을 수 있습니다. 둘 다 팩의 모든 유형이 같은지 여부에 대한 진정한 거짓 표시 자이며 동일한 경우 공통 유형에 액세스 할 수 있습니다. 우리는 일반적인 유형이 있고, 크기를 확인했으면, 우리는 그 위에 배열과 루프를 초기화 팩을 사용할 수 있습니다, 그래서 우리는 우리의 함수 내에서 짜증나는 가변 스타일의 프로그래밍 일을 계속 할 필요가 없습니다 :

template <std::size_t N> 
struct System { 

    template <class ... Ts> 
    void fun(Ts&... ts) { 
     static_assert(sizeof...(Ts) == N, "Wrong number of parameters!"); 
     using same = all_same<Ts...>; 
     static_assert(same::value, "All types must be the same!"); 
     std::array<std::reference_wrapper<typename same::same_type>, N> x{ts...}; 
     for (auto& e : x) { std::cerr << e << std::endl; } 
    } 
}; 

정확한 요구에 맞게이 솔루션을 수정하면 C++에 대한 전문성이 약간 필요할 것이며, 또한 까다로운 특정 상황, 예를 들어 문자열 리터럴과 std::string 또는 암시 적으로 변환 가능한 데 사용 된 다른 유형을 모두 전달하면 오류가 발생합니다. 그래도 도움이되면 도움이되기를 바랍니다. 실제 예 : http://coliru.stacked-crooked.com/a/08ac23da33deb8ef.

+0

이것이 내가 찾던 해결책이다. variadic 템플릿에 대한 나의 첫 번째 시도는 엉망이었다. 그러나, 좀 더 복잡한 템플릿 유형으로 표준 : : reference_wrapper에 문제가 있습니다. 어쨌든 감사합니다! – thewoz

1

가능한 해결책은 클래스의 본체 내부의 함수를 정의 할 수있다 (김에 욕실 : 이름 system() 피하기 : 표준 기능과 충돌 할 수있다), SFINAE를 사용

template <std::size_t N> 
class systemClass 
{ 
    private: 
     std::array<FooType, N> matrices; 

    public: 
     template<typename T, std::size_t M = N> 
     typename std::enable_if<M == 1U>::type fun(T & a) { } 

     template<typename T, std::size_t M = N> 
     typename std::enable_if<M == 2U>::type fun(T & a, T & b) { } 

     template<typename T, std::size_t M = N> 
     typename std::enable_if<M == 3U>::type fun(T & a, T & b, T & c) { } 
}; 

Moreover I would like that the headers functions will be autogenerate based on the template parameter N. I tried to use variadic template but without fortune.

다음과 같이 나는 UnholySheep과 동의합니다 : 당신이 정확히 원하는 것은 무엇인지 명확하지 않지만 해결책은 코드를 생성하는 쉘 스크립트 일 수 있습니다.

+0

죄송합니다. 내 질문이 명확하지 않다는 것을 알고 있습니다. 나는 또한 쉘 스크립트가 해결책이라고 생각한다. 어쨌든 나는 또한 당신의 솔루션을 좋아하지만 다른 fun() 함수를 지정하는 것을 피하기 위해 @nir 솔루션은 잘 작동한다. – thewoz

3

integer_sequence 및 별칭 템플릿을 사용하면 foo을 더 일반적인 것으로 만들 수 있다고 생각합니다.(integer_sequence는 ++ (14)는 C 있지만 C++ (11 개) 구현도 존재) :

#include <utility> 
#include <array> 

template <class T, std::size_t> 
using typer = T; 

template <std::size_t N, class = std::make_index_sequence<N>> 
struct S; 

template <std::size_t N, std::size_t... Is> 
struct S<N, std::index_sequence<Is...>>{ 

    std::array<int, N> matrices; 

    template <class T> 
    void foo(typer<const T&, Is>... args) { 
     int dummy[] = { ((matrices[Is] = args), void(), 0)... }; 
     static_cast<void>(dummy); 
    } 
}; 

int main() { 
    S<3> s; 
    s.foo(1, 2, 3); 
} 

[live demo]

+0

이것은 N이 알려져 있고 추론 할 필요가 없다는 사실을 이용하여 확실히 내 솔루션보다 우수합니다. –

+0

@NirFriedman 잘 다른 한편으로는 그것은 배경/experiance 색인을 붙이는 constexpr를 필요로하고, 언뜻 보면 명백하지 않을지도 모른다. .. –

+1

예. 그러나 더 우아하다. IMHO 일단 당신이 이미 그것을 보았 으면 그것은 분명합니다. 그러나, 나는 그것을 무료 함수에 적용하는 아주 좋은 방법을 실제로 보지 못했습니다. 구현 기능으로 전달해야하는 것처럼 보이지만, 제대로 구현되지 않았기 때문에 다소 불리합니다. –

1

당신은 당신의 기능 가변 인자를 만들지 만, 유일한 매개 변수의 오른쪽 숫자를 수용 할 수 있습니다. 그 결과는 다음과 같습니다에만 매개 변수의 수는 N 같은 경우는 함수가 존재 할 수있는 경우

template <std::size_t N> 
struct system { 
    template<typename... Ts> 
    auto fun(Ts&&... ts) -> std::enable_if_t<(N == sizeof...(Ts))> { 
     // function content 
    } 

private: 
    std::array<cv::Mat, N> matrices; 
}; 

이 있습니다.