2017-11-26 5 views
1

I 다음 예제 코드가 있습니다static_cast를 사용하여 가변 CRTP 초기화 <Base> (* this) ... : 합법적입니까?

#include <iostream> 
#include <initializer_list> 
struct foo { int x{}; }; 
struct bar { double y{}; }; 

template<typename... Base> 
struct Foo : Base... 
{ 
    constexpr auto init_int(int x) const 
    { return Foo<foo, Base...>{foo{x}, static_cast<Base>(*this)...}; } 
    constexpr auto init_double(double x) const 
    { return Foo<bar, Base...>{bar{x}, static_cast<Base>(*this)...}; } 
}; 

int main() 
{ 
    constexpr auto f = Foo<>{}.init_double(.5).init_int(1234); 
    static_assert(f.x == 1234); 
    static_assert(f.y == 0.5); 
} 

이 (-std = C++ 1Z와) 최근 연타 및 GCC 모두에서 작동하는 것 같다,하지만 MSVC2017에. 그래서 나는이 법적 C++의 것을 확실하지 않다 : 그것은처럼 보이는 생성자를 합성하는 것 같다

Foo(Base1 b1, Base2 b2, Base3 b3, ...): 
    Base1{b1}, 
    Base1{b2}, 
    Base3{b3}, 
    ... { } 

나는 안전하게이 작업을 수행 할 수 있으며이 잘 정의되어 보장 할 수?

+1

_ "하지만 MSVC2017에서"_ 나는 그것이이 있다면 더 관심이있을 것 (푸 슈퍼 유형에 따라 템플릿 인수를 가지는 템플릿 특수화에서 상속하지 않습니다) 여기에는 CRTP를 볼 수 없습니다 다른 방법 라운드. – user0042

+0

일반적으로 말하자면, Clang과 GCC가 MSVC를 사용하지 않는 한 코드를 받아들이면 C++ 코드가 유효하지 않음을 나타내는 부호가 아닙니다. – StoryTeller

+0

동의하지만 미안보다 안전합니다 : p –

답변

3

C++ 17부터 집계에는 집계 유형의 공개 비 가상 기본 클래스가있을 수 있습니다. foobar은 집계이므로 Foo<foo,bar>은 집계이므로 중괄호 초기화시 집계 초기화이 사용됩니다.

그래서 코드는 C++ 17 이상에서 유효합니다 (이전에는 아닙니다). 'aggregate constructor'은 합성되지 않습니다. 단지 중괄호 초기화가 집계에 대한 특별한 해석을한다는 것입니다. BTW

, 나는