2

생성자 초기화 목록에서 ADL을 활성화하려면 어떻게해야합니까? 예를 들어 의 네임 스페이스 수준이 abs 인 경우를 예로 들어 보겠습니다. 이제 생성자에 전달 된 인스턴스의 절대 값으로 멤버를 초기화하는 클래스 Foo을 작성하고 싶습니다. 그것은 사용하는 네임 스페이스 수준 abs 존재하는 경우와 그렇지 않은 경우 std::abs해야합니다생성자 초기화 목록의 ADL

template<typename T> 
struct Foo 
{ 
    T _data; 

    Foo(T data): 
     _data(abs(data)) // I want find abs with ADL here 
    {} 
}; 

사용하여 선언은 어쨌든 클래스 범위에서 금지하고 나는 네임 스페이스를 "오염"싶지 않아요. 생성자 초기화 목록에서 ADL이 작동하도록하려면 어떻게해야합니까?

+0

'Foo'유형이 ​​아닌 'T'유형의 회원이라고 가정합니다. 맞습니까? – pmr

+1

약간 관련성이 있음 : http://stackoverflow.com/questions/7635939/how-do-i-write-an-adl-enabled-trailing-return-type-or-noexcept-specification –

답변

6

당신은 직접 initialiser 내에서이 문제를 해결할 수 있습니다 목록에서 람다 표현식을 사용하여 필요한 헬퍼 함수를 ​​인라인으로 작성할 수 있으며 헬퍼 함수는 using std::abs;을 포함 할 수 있습니다.

template<typename T> 
struct Foo 
{ 
    T _data; 

    Foo(T data): 
     _data([&](){ using std::abs; return abs(data); }()) 
    {} 
}; 
+2

+1 매우 영리합니다. – 0x499602D2

4

당신은 거기에 ocurr하는 ADL을 무료 또는 static 지역 도우미 함수를 생성 할 수 있습니다 :

template <typename T> 
struct Foo 
{ 
    T _data; 

    Foo(T data): 
     _data(abs(data)) 
    {} 

    template <typename X> 
    using delete_reference = typename std::remove_reference<X>::type; 

    template <typename U> 
    static delete_reference<U> abs(U&& x) 
    { 
     using std::abs; 
     return abs(std::forward<U>(x)); 
    } 
}; 
+0

나는 컴파일을 의심하고, -const lvalue - 임시 객체에 대한 참조입니다. – nosid

+0

@nosid lvalue-reference는 어디에서 반환합니까? – 0x499602D2

+0

@ 0x499602D2 'abs '의 반환 값 타입이'int'이고'Foo '인스턴스화시. 'data'는 좌변 값이므로'U'는 좌변 값 참조 타입으로 추론됩니다. – hvd

1

사용이 도우미 함수 :

namespace detail 
{ 
    template <typename Arg> 
    auto invoke_abs(Arg&& arg) 
    { 
     using std::abs; 
     return abs(std::forward<Arg>(arg)); 
    } 
} 

Foo(T data) 
    : _data{detail::invoke_abs(std::forward<T>(data))} 
{ } 
+0

+1 이미 게시 된 답변을 컴파일하기 위해 +1하지만 자동 추론 반환 유형은 실제로 람다 함수 외부에서 유효하지 않으므로 C++ 11 호환 모드의 컴파일러에서는 실패합니다. (나는 내 ​​대답을 올렸을 때 그것을 깨닫지 못했습니다.) – hvd