2016-08-31 2 views
-1

항상 적절한 형식의 0을 반환하는 zero() 템플릿 함수를 작성하려고합니다. 이것은 기본 유형에 대해서는 사소한 것이지만 사용자 정의 유형 (자체 과부하를 제공 할 수 있음)에 대해 유사한 동작을 원합니다.적절한 형식의 "0"을 반환하는 C++ 함수

template <typename T> 
T zero() { 
    return T{}*0; // Clearly not correct for all types, but known incorrect cases should be specialized 
} 

template <> 
int zero<int>() { return 1; } // intentionally wrong for testing 

하지만 전문성을 나타내는

cout << zero<int>() << endl; 

출력 0을 호출 호출되지 않는 예를

auto i = zero<int>() // i is an in 
auto d = zero<double>() // d is a double 
auto m = zero<Matrix2d>() // m is a Matrix2d with all elements initialized to zero. 

를 들어 내가있는 것은 이것이다. 내가 도대체 ​​뭘 잘못하고있는 겁니까?

* 참고 :. 사용 케이스 :: 축적 수 std하지만, 시작 값은 항상 0입니다 상상과 유사하며 우리가 그것을 전달하는 사용자를 필요로하지 않으

UPDATE 로 몇 명의 주석가들이 지적했는데, 이것은 Ideone에서 작동합니다. 내 특정 구현에 대한 무언가가 그것을 깨고있다. 내가 가진 :

zero.h :

template <typename T> 
constexpr T zero() { 
    return T{}*0; 
} 

zero.cpp :

#include "zero.h" 
template <> 
constexpr int zero<int>() { return 1; } 

MAIN.CPP :

#include <iostream> 
#include "zero.h" 

using namespace std; 
int main(int argc, char **argv) { 
    cout << "int: " << zero<int>() << endl; 
} 
+2

[값 초기화] (http://en.cppreference.com/w/cpp/language/value_initialization)라는 바퀴를 재발 명하려고합니다. 귀하의 클래스에 대한 기본 생성자를 만들고 그것을 완료하십시오. –

+4

왜 변수 템플릿을 사용하지 않습니까? '템플릿 constexpr T 영점 = T {};' –

+1

[재생할 수 없음] (http://ideone.com/T4al10) – user463035818

답변

0

".cpp" 개의 파일에서 템플릿을 사용하지 마십시오. 일부 유용한 references.

zero.h :

봅니다 헤더 파일에 모든 것을 이동

template <typename T> 
T zero() { 
    return T{}*0; 
} 

template <> 
int zero<int>() { return 1; } 

을 그리고 파일 zero.cpp을 삭제합니다.

편집 : 당신은 비주얼 스튜디오를 사용하는 경우

, this이 유용 할 수있다 :

이 오류는 또한 비주얼 스튜디오 .NET에서 이루어졌다 컴파일러 준수 작업의 결과로 생성됩니다 2003 :. 코드가 Visual Studio .NET 2003 및 Visual Studio .NET 버전의 Visual C++에서 유효한 경우 템플릿 <>을 제거하십시오.

-1

사용 기본 유형 T의 생성자 또는 0 인수를 사용 :

template <class T> 
T zero() 
{ 
    return T() /* or T(0)*/; 
} 
+0

IMO이 게시물은 질문에 대답하지 않습니다. 나는 당신의 * "스타일"*이 특정 의미에서 더 견고하다는 것에 동의하지만, 질문은 "왜 그 코드는 1 대신에 0을 인쇄 하는가"라는 것입니다. –

+0

그가 쓴 것이 맞다면 ... –

+0

@BiagioFesta 작전은 MCVE가 필요하므로 답할 수 없습니다. 당신과 다른 사람이 OP가 말한 것을 그가 보여 주듯이 그가 얻을 수있는 것은 재생산이 불가능합니다. – NathanOliver

2

템플릿 기능 전문화를 절대로 사용하지 마십시오. 거의 절대.

template<class T>struct tag_t{}; 
template<class T>constexpr tag_t<T> tag{}; 

이렇게하면 유형을 값으로 전달할 수 있습니다. 이제

namespace utility{ 
    template<class T> 
    T zero(){ return zero(tag<T>);} 

    template<class T> 
    T zero(tag_t<T>) { return T{}*0; } 
} 

기본 구현, 작동 단순히 ( std의 유형 또는 utility 또는 내장 타입) X의 공간 중 하나에 zero(tag_t<X>)을 무시하지 않는 특정 유형에 대한 지원을 추가합니다.

namespace math{ 
    struct matrix2d; // define it 
    inline matrix2d zero(tag_t<matrix2d>){ return matrix2d::zero; } 
} 

ADL은 올바른 제로 당신 utility::zero<X>() 경우 찾을 수 있습니다.

템플릿 함수의 특수화는 템플릿 유형의 오버로드 또는 특수화와 같이 작동합니다. 깨지기 쉽고 그 규칙은 독특합니다. 그것은 거의 모든 문제에 대한 최상의 솔루션입니다. 그것을 피하십시오.

템플릿 기능 전문화가 깨지기 쉽기 때문에,보기에 표시되지 않은 세부 사항이 놀라워하지 않습니다. 예를 들어 OP에 게시 된 코드는 순진하게 전사 될 때 분명히 깨지지 않습니다. 그것은 여전히 ​​나쁜 생각입니다 : 허영심 위에, 그것은 또한 사람들이 네임 스페이스 보스에 코드를 작성하여 그것을 종료시키고 네임 스페이스에 0의 특수화를 추가 한 다음 네임 스페이스 보우로 돌아가도록 강요합니다. 그렇게하는 동안 제로의 기본 전문은 보이지 않으면 안되며, 의존성을 망칠 필요가 있습니다. 그것은 끔찍해.

+0

함수 템플릿 지정과 관련하여 이상한 규칙이 있음을 알고 있습니다 만,이 경우에는 특별히 시도하고 있습니다. 인수를 피하십시오. 템플릿을 T zero (const T & ex)로 템플릿을 오버로딩하면된다. int zero (const int & ex) {return 1; } – ryan0270

+0

@ryan'zero ()'은 위의 코드와 작동합니다. – Yakk

+0

미안하지만, 너무 빠르면 준비가 끝납니다. – ryan0270

0

"사용 사례는 std::accumulate과 비슷하지만 시작 값은 항상 0이며 사용자가이를 전달할 필요가 없다고 가정합니다." 공교롭게도

, 내 도구 상자에서 정확히이 있습니다

template <typename FwdIter> 
inline auto accumulate(FwdIter begin, FwdIter end) 
     -> typename std::iterator_traits<FwdIter>::value_type 
{ 
    return std::accumulate(begin, end, 
     typename std::iterator_traits<FwdIter>::value_type()); 
} 

관련 표현이 바로 반복자 타입 주어진 제로 값을 계산 typename std::iterator_traits<FwdIter>::value_type()입니다. value_type은 종속 형식이므로 typename이 필요합니다.

관련 문제