그래서 현대 C ++의 풍미로 내적 제품 ( https://en.wikipedia.org/wiki/Dot_product ) 을 구현하려고 시도 하고 다음 코드를 생각해 냈습니다.
#include <iostream>
template<class... Args>
auto dot(Args... args)
{
auto a = [args...](Args...)
{
return [=](auto... brgs)
{
static_assert(sizeof...(args) == sizeof...(brgs));
auto v1 = {args...}, i1 = v1.begin();
auto v2 = {brgs...}, i2 = v2.begin();
typename std::common_type<Args...>::type s = 0;
while( i1 != v1.end() && i2!= v2.end())
{
s += *i1++ * *i2++;
}
return s;
};
};
return a(std::forward<Args>(args)...);
}
int main()
{
auto a = dot(1,3,-5)(4,-2,-1);
std::cout << a << std::endl;
}
온라인 : https://gcc.godbolt.org/z/kDSney 및 cppinsights
좋게 함께 컴파일하여 실행하는 상기 코드 g++
하지만 clang
(그리고 icc
및 msvc
그것에) 초크 :
clang++ ./funcpp.cpp --std=c++17
./funcpp.cpp:12:4: error: 'auto' deduced as 'std::initializer_list<int>' in declaration of
'v1' and deduced as 'const int *' in declaration of 'i1'
auto v1 = {args...}, i1 = v1.begin();
^ ~~~~~~~~~ ~~~~~~~~~~
./funcpp.cpp:28:11: note: in instantiation of function template specialization
'dot<int, int, int>' requested here
auto a = dot(1,3,-5)(4,-2,-1);
^
1 error generated.
이제, 내가의 정의를 어기면 v1
, v2
, i1
, i2
와 같은 :
auto v1 = {args...} ;
auto i1 = v1.begin();
auto v2 = {brgs...};
auto i2 = v2.begin();
clang
그리고 msvc
아무 문제가 없다, icc
여전히 초크 :
<source>(10): error: static assertion failed
static_assert(sizeof...(args) == sizeof...(brgs));
^
detected during instantiation of "auto dot(Args...) [with Args=<int, int, int>]" at line 30
compilation aborted for <source> (code 2)
Execution build compiler returned: 2
그러나 문제 static_assert
를 제거 icc
하면 코드를 컴파일하는 데 아무런 문제가 없습니다.
그리고 (일반적인) 질문 외에도 : 옳고 그 이유 :) 구체적인 질문은 다음과 같습니다.
에 따르면 [dcl.spec.auto]
:
자리 표시 자 유형을 대체하는 유형이 각 공제에서 동일하지 않은 경우 프로그램이 잘못 구성됩니다.
clang
해당 행에 두 가지 유형이 정의되어 있음을 올바르게 식별했습니다. 'auto' deduced as 'std::initializer_list<int>' in declaration of 'v1' and deduced as 'const int *' in declaration of 'i1'
따라서 다음 사항에 대한 귀하의 의견을 듣고 싶습니다.
- 내가 (에 언급되지 않은이 특정 상황을 고려 문서화되지 않은 g ++ 확장 명중했다 https://gcc.gnu.org/onlinedocs/gcc-9.2.0/gcc/C_002b_002b-Extensions.html#C_002b_002b-Extensions을 내 지식 g ++ 이후를) 자동 선언 목록에서 다른 유형을 올바르게 처리합니다.
- 또는 우연히 g ++은 두 유형이 다른 것으로 추론하지 않았습니다 (... hm ...)
- 또는 다른 것?
이 긴 질문을 읽어 주셔서 감사합니다. (왜 누군가가 대답 할 수 있다면 보너스로 icc
실패하는 것이 static_assert
좋을 것입니다.)
auto v = { 1, 2, 3 }, i = v.begin();
. 동일한 insiede 람다를 컴파일한다는 것을 이해하지 마십시오. 최소 예 : gcc.godbolt.org/z/a5XyxU . 사용자 정의 functor ( gcc.godbolt.org/z/eYutyK ) 또는 템플릿 함수 ( gcc.godbolt.org/z/jnEYXh) 내에서도 컴파일 됩니다.
template <typename T> void f(T a) { auto v = {a}, i = v.begin(); }
과 같이 호출 될 때 f(1);
입니다. 다시 작성 void f(int a) { /* same body */ }
하면 컴파일 오류가 발생합니다.
std::forward<Args>(args)
여기 의 용도는 무엇입니까 ?