템플릿과 함께 인라인 키워드를 사용하는 것이 합리적입니까?


119

템플릿이 헤더 내에서 정의되고 컴파일러가 함수를 인라인하는 것이 유리한지 판단 할 수 있기 때문에 어떤 의미가 있습니까? 현대 컴파일러는 함수를 인라인해야 할 때를 더 잘 알고 inline힌트를 무시한다고 들었습니다 .


편집 : 두 답변을 모두 수락하고 싶지만 불가능합니다. 문제를 해결하기 위해 나는 대부분의 표를 받았으며 그가 공식적으로 옳았 기 때문에 phresnel 의 답변을 수락 하고 있지만, 코멘트에서 언급했듯이 나는 PuppyComponent 10 의 답변도 다른 관점에서 올바른 것으로 간주합니다. .

문제는 C ++ 의미 체계에 있으며 inline키워드 및 인라인의 경우 엄격하지 않습니다 . phresnel 은 " 원하는 경우 인라인 작성"이라고 말하지만 실제로 의미 inline는 원래 의미에서 Puppy가 말한 것처럼 "컴파일러가 ODR 위반에 대해 괴롭히는 것을 막는"지시문으로 발전했기 때문에 명확하지 않습니다 .

답변:


96

무관하지 않습니다. 아니요, 모든 기능 템플릿이 inline기본적으로 제공되는 것은 아닙니다 . 표준은 명시 적 전문화 ([temp.expl.spec]) 에서도 명시 적입니다.

다음이 있어야합니다.

a.cc

#include "tpl.h"

b.cc

#include "tpl.h"

tpl.h (명시 적 전문화에서 가져옴 ) :

#ifndef TPL_H
#define TPL_H
template<class T> void f(T) {}
template<class T> inline T g(T) {}

template<> inline void f<>(int) {} // OK: inline
template<> int g<>(int) {} // error: not inline
#endif

이것을 컴파일하십시오.

g++ a.cc b.cc
/tmp/ccfWLeDX.o: In function `int g<int>(int)':
inlinexx2.cc:(.text+0x0): multiple definition of `int g<int>(int)'
/tmp/ccUa4K20.o:inlinexx.cc:(.text+0x0): first defined here
collect2: ld returned 1 exit status

inline명시 적 인스턴스화를 수행 할 때 명시 하지 않으면 문제가 발생할 수도 있습니다.

요약하자면 : 완전히 전문화되지 않은 함수 템플릿, 즉 하나 이상의 알 수없는 유형을 포함하는 템플릿의 경우를 생략 inline하고 오류를 수신 할 수 없지만 여전히 그렇지 않습니다 inline. 전체 전문화의 경우, 즉 알려진 유형 만 사용하는 경우 생략 할 수 없습니다.

제안 된 경험 법칙 : inline의미가 있으면 작성 하고 일관성을 유지하십시오. 그것은 당신이 할 수 있기 때문에 할 것인지 말 것인지에 대해 덜 생각하게 만듭니다. (이 경험 법칙은 Vandevoorde / Josuttis의 C ++ 템플릿 : The Complete Guide를 준수합니다 .)


2
사실이라고 쓸 수 있습니다. 하지만 그렇게 보이지만 인라인을 의미하지는 않습니다. Vandevoorde 및 Josuttis에 또한 상태를 정확히에서 C ++ 템플릿 : 완전한 가이드
세바스찬 마하

43
명시 적 전문화는 템플릿이 아닙니다.
Puppy

2
@DeadMG : 그러나 조회시 전체 전문화보다 일반 함수가 선호되므로 템플릿이 아니고 템플릿이 아닌 경우에는 무엇입니까?
Sebastian Mach

13
이 대답은 틀 렸습니다. 템플릿의 명시 적 전문화는 템플릿이 아니라 함수입니다. 그 기능 inline은 전문화 된 템플릿이으로 표시되어 있기 때문 이 아닙니다 inline. 따라서 inline템플릿은 완전히 관련이 없습니다. 해당 기능이 있어야하는지 여부 inline는 템플릿 전문화를 통해 생성되는 것과 관련이 없습니다 (사용시기를 다루는 이보다 더 나은 답변이 있습니다 inline). 아래 @Puppy의 대답은 정확하지만 이것은 아닙니다. inline템플릿에 추가 하는 것은 관련이 없으며 clang-tidy실제로 제거됩니다.
gnzlbg

6
또한이 예제는 일반 기능에 대한 ODR 문제를 보여줍니다 (템플릿과 관련이없는 동작). 즉 보여주는 시도 inline무관하지되면, 예를 명시 적으로 전문의 경우 커버해야 template<> void f<>(int) {} 없이inline 키워드를. 그러나 inline템플릿 의 지정자 를 변경해도 템플릿을 표시했는지 여부 inline는 관련이 없기 때문에 아무런 차이 가 없습니다.
gnzlbg

34

관련이 없습니다. 모든 템플릿은 이미 있습니다. inline2012 년 현재 inline키워드 의 유일한 사용은 컴파일러가 ODR 위반에 대해 불평하는 것을 막는 것입니다. 당신은 절대적으로 정확합니다. 현재 세대의 컴파일러는 자체적으로 인라인 할 내용을 알고 있으며 번역 단위 간에도 그렇게 할 수 있습니다.


11
표준은 모든 템플릿이 인라인이라고 명시하지 않습니다.
Sebastian Mach

16
@phresnel : 그러나 템플릿은-마킹 된 inline함수 와 동일한 의미를 갖습니다 (즉, 여러 개의 동등한 정의가 링커에 전달되어 하나를 선택할 수 있음). 그것은 인라인이 아니라 inline키워드 의 실제 기능입니다 .
Ben Voigt 2012

2
@BenVoigt : ODR의 의미를 알고 inline있습니다. 아마도 아래 (또는 선택한 정렬에 따라 위) 내 대답을 엿볼 수 있습니다. 전문화되지 않은 템플릿의 경우 당연히 맞지만 공식적으로 동일하지는 않습니다.
Sebastian Mach

3
@DeadMG : C ++에는 함수 템플릿이 헤더 파일에 구현되어야한다는 요구 사항이 없습니다. 어디서나 구현할 수 있습니다. 이를 반영하기 위해 inline인라인으로되어있는 태그를 지정 하는 것이 좋습니다 . 일반적으로 차이는 없지만 표준에서는 동일하지 않으며 모두 인라인이 아닙니다. 나는 "관련이 없다"는 입장을 받아들이지 만, 표준에 따라 모든 템플릿이 인라인되지는 않으며 C ++ 사용자로서 만 보이는 것처럼 보입니다.
Sebastian Mach

7
명시 적 전문화가 템플릿이 아니라는 ( 물론 그렇게 말한 후에 명백한) 수락 된 답변에 대한 귀하의 의견 은 아마도이 페이지에서 가장 도움이 될 것입니다. 답변에 추가해 주시겠습니까?
Kyle Strand

6

당신이 제안 inline했듯이은 컴파일러에 대한 힌트이며 더 이상은 없습니다. 무시하거나 실제로 인라인으로 표시되지 않은 함수를 인라인하도록 선택할 수 있습니다.

사용하여 inline각 컴파일 단위가 같은 템플릿 클래스에 대해 별도의 개체를 만드는 것이 문제의 둘레에 얻기의 (가난한) 방법이 사용하는 템플릿을하는 것 다음 링크시 중복 문제 원인. 사용하여 inline이름 맹 글링 링크시 이름 충돌 라운드 있지만 크게 부풀어 코드의 비용으로 얻을 수있는 다른 운동한다 (나는 생각한다).  

Marshall Cline은 여기서 제가 할 수있는 것보다 더 잘 설명합니다 .


@Xeo : 예전에는 그렇지 않았습니다. 여기에서 확인하십시오 : gcc.gnu.org/onlinedocs/gcc-4.0.4/gcc/… 나는 그것이 더 최근에 변경되었다고 가정합니다 . 그것이 내가 과거 시제로 말한 이유입니다.
구성 요소 10

2
@Xeo : 함수 템플릿이 항상 인라인이라는 표준 부분을 알려 주시겠습니까? 왜냐하면 그들은 그렇지 않기 때문입니다.
Sebastian Mach

@phresnel : 흥미 롭습니다. 표준에서 읽었습니다. 아마도 함수 템플릿이 ODR ( §14.5.5.1 p7 & p8) 에서 면제된다는 사실과 혼동했을 수도 있습니다. 안타깝게도 잘못된 댓글을 삭제했습니다.
Xeo

@Component 10 왜 당신은 점점 라운드 컴파일 문제의 빈약 한 방법이라고 생각
카필
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.