2016-11-16 8 views
3

나는 다음과 작은 도서관 쓰고 피하기 위해 구조체에 숫자를 포장의 단점 :장점과 암시 적 변환

using foo_t = int; 
using bar_t = int; 

baz_t create_baz(foo_t foo, bar_t bar = default_bar); 

와 나는 또한 단지 줄을 취하는 create_baz 기능을 갖고 싶어를 :

baz_t create_baz(bar_t bar); 

하지만 그 create_baz의 부도 첫 번째 버전과 충돌합니다 - foo_t 이후 및 bar_t은 동일합니다. 그래서, 나는 생각했다 : 아마도 나는 종류가 다른, 심지어는 호환되지 않는, 그리고 수 있도록

struct foo_t { int value; } 
struct bar_t { int value; } 

(또는 구조체에 그들 중 하나를 포장), 내가 가지고있을거야해야 두 번째 create_baz 그 .

구조체는 사용하기가 쉽지 않습니다. 그러나이 결정에 대해 고려해야 할 다른 장단점이 있습니까?

내 질문은 주로 C++에 관한 것이지만 C 언어와 관련이있다 (첫 번째 함수의 두 번째 매개 변수는 무시한다).

+0

비슷한 대답을 할 필요가 없었기 때문에 대답이 없었습니다. 구조체를 사용하면 불편하지 않아서'x = foo;'또는'x = foo.value; '를 쓰지 않습니다. 큰 차이를 만들어라. 그리고 코드를 명확하게 만들려면'auto & v = foo.value; '를 사용할 수 있습니다. 구조체를 도입 한 이유를 문서화하십시오. – stefaanv

+0

구조체를 사용하여 서로 다른 유형의 'int'값을 구분할 수 있습니다. 그러나 C에는 이름 변환이 없으므로 함수 오버로딩이 없으므로 관계없이 다른 함수 이름이 필요합니다. –

+0

'strong typedef'는 우리가 가지고 있지 않은 것입니다. 하지만 당신은 언제나 어떤 사용자 태그를 취하고'operator int'를 정의하는 래퍼'IntClass'를 생성 할 수 있습니까? – Arunmu

답변

2
다음은 정확한 질문에 대한 답변하지

하지만 BOOST_STRONG_TYPEDEF 호환되지 않는 형식 정의를 만들기 위해 잘 작동하는 것 같다 :

#include <boost/strong_typedef.hpp> 
// Only the header is required. No linking, no runtime dependencies. 

BOOST_STRONG_TYPEDEF(int, foo_t); 
BOOST_STRONG_TYPEDEF(int, bar_t); 

void create_baz(foo_t foo, bar_t bar = static_cast<bar_t>(1)) {} 
void create_baz(bar_t bar) {} 

int main() 
{ 
    // Assigning (or initializing with) literals seems to be 
    // the only inconvenient thing about strong typedefs. 
    foo_t a = static_cast<foo_t>(1); 
    foo_t b = static_cast<foo_t>(2); 

    a = b; // Operators work well. 
    std::cout << a+b << std::endl; // Even overloaded ones. 

    create_baz(a); // No errors, no ambiguity. 
    return 0; 
} 
+0

나는 이것을 좋아하지만 : 1. 다양한 연산자의 정의가 아닌 구조체로 감싸는 것과 어떻게 다른가? 2. int로 돌아가는 것은 어떨까요? 3. Boost에 대한 의존성을 만드는 것이 나에게 문제가된다. 헤더 만 포함하더라도. – einpoklum

+1

@einpoklum 1. 여기서는 아무런 차이가없는 것처럼 보입니다. Boost는 추가 작업을하지 말고 모든 작업자를 정의했습니다. 2.'int c = a;'를 의미합니까,'a'는 강력하게 typedef되어 있습니까? 명시 적 캐스트없이 작동합니다. 3. OK는 종종 원하지 않는 의존성입니다. 임시 해결책으로'#include '(이 유일한 행)를 컴파일러의'g ++ -E' 또는 비슷한 옵션으로 컴파일하고 프로젝트에 출력을 헤더로 추가 할 수 있습니다. – Sergey

+0

또한'enum class foo_t : int {};'트릭 – sp2danny

1

A, 공통 기본 및 명백한 기술 함수 호출 여분을 추가하고 명확하게하기 위해, 매개 변수를 사용하고 오버로드에 의존합니다.
표준 템플릿 라이브러리의 일부 클래스 만 사용하는 경우가 너무 일반적입니다.

예를 들어, std::allocator_arg_t의 목적은 무엇 고려해

[...] 할당 인식 객체의 생성자의 오버로드와 멤버 함수를 명확하게하는 데 사용되는 빈 클래스 유형 [...]

는 그것은 std::function, std::tuple, std::promisestd::packaged_task 의해 사용된다.

이러한 클래스의 생성자 목록을 사용하면 어떻게 사용되는지 쉽게 알 수 있습니다.

또 다른 예는 후위 증가/감소 연산자입니다.
함수 선언을 접두사 증가/감소 연산자와 구별하는 데 도움이되는 더미int 매개 변수가 있습니다.

T& operator++(T&) 

수스 :이다

전화는 추가 매개 변수를 제공 할 필요가 없으며 실제로는 함수 선언을 명확하게하는 유일한 역할, 그래서 그것은 부자연 여기
T& operator++(T&, int) 

예.

어쨌든 당신은 무엇을 할 수 있습니까?

struct bar_arg_t {}; 

을 그리고 두 번째 함수 선언에서 사용 :
이 하나 같이 태그를 정의 할 수 있습니다

빈 클래스에 불과하다
baz_t create_baz(bar_arg_t, bar_t bar); 

, 더미 변수 목적 그 중 하나는 당신이 전화를 모호하게하는 데 도움이되는 것입니다.