나는 매개 변수 팩을 통해 재귀 템플릿 기능을 가지고있다. 본질적으로 something.Get<A,B,C>()
을 something.Get<A>().Get<B>().Get<C>()
으로 매핑하기위한 것입니다. 재귀 템플릿 함수가 Clang으로 컴파일되지 않습니까?
이
은 (겹 아래 완전 독립형 소스)을 수행하여 달성 할 수first_true
에 해당하는 첫 번째 요소의 인덱스를 반환
template <typename... Pack> class Struct {
std::tuple<Pack...> mTuple;
template <typename Type> auto &GetRef_internal() {
return std::get<first_true<std::is_same<Type, Pack>::value...>::value>(
mTuple);
}
public:
template <typename Current> Current &GetRef() {
return GetRef_internal<Current>();
}
template <typename Current, typename... Next,
typename std::enable_if<sizeof...(Next) != 0>::type * = nullptr>
auto &GetRef() {
auto current = GetRef_internal<Current>();
return current.GetRef<Next...>();
}
};
.
이 g 용 ++로 컴파일하고 겉으로는 MSVC 너무 online compiler를 사용하여. clang ++로 컴파일 할 때 다음과 같은 오류가 발생합니다.
test.cxx:40:31: error: expected '(' for function-style cast or type construction
return current.GetRef<Next...>();
~~~~^
test.cxx:38:9: error: cannot deduce return type 'auto &' for function with no return statements
auto &GetRef() {
^
test.cxx:48:12: note: in instantiation of function template specialization 'Struct<Struct<int, Struct<float, float> >, Struct<char>, int>::GetRef<Struct<int, Struct<float, float> >, Struct<float, float> , nullptr>' requested here
.GetRef<Struct<int, Struct<float, float>>, Struct<float, float>>();
^
2 errors generated.
어떤 일이 발생할 수 있습니까?
p.s. 실제 '생산 코드'는보기가보기보다 유용하지만 여기에 게시하는 것이 너무 많습니다.
============================================== ===========================
#include <tuple>
#include <type_traits>
// Template to check if condition holds true for all members of a parameter
// pack.
template <bool... b> struct BoolArray {};
template <bool... b>
using all_true = std::is_same<BoolArray<b...>, BoolArray<(b, true)...>>;
//helper type trait
template <bool... b> struct first_true {
template <
unsigned index = 0,
typename std::enable_if<index<sizeof...(b)-1>::type * =
nullptr> static constexpr unsigned check() {
return std::get<index>(std::make_tuple(b...)) ? index : check<index + 1>();
}
template <unsigned index = 0,
typename std::enable_if<index >= sizeof...(b)-1>::type * = nullptr>
static constexpr unsigned check() {
return std::get<index>(std::make_tuple(b...)) ? index : 0;
}
static constexpr unsigned value = first_true<b...>::check();
};
//The actual problem struct
template <typename... Pack> class Struct {
std::tuple<Pack...> mTuple;
template <typename Type> auto &GetRef_internal() {
return std::get<first_true<std::is_same<Type, Pack>::value...>::value>(
mTuple);
}
public:
template <typename Current> Current &GetRef() {
return GetRef_internal<Current>();
}
template <typename Current, typename... Next,
typename std::enable_if<sizeof...(Next) != 0>::type * = nullptr>
auto &GetRef() {
auto current = GetRef_internal<Current>();
return current.GetRef<Next...>();
}
};
int main() {
// Define a random nested struct
Struct<Struct<int, Struct<float, float>>, Struct<char>, int> myStruct;
// Then retrieve one of the substructures to instantiate the template
auto substruct =
myStruct
.GetRef<Struct<int, Struct<float, float>>, Struct<float, float>>();
return 0;
}
이 일했다! 오늘 새로운 것을 배웠습니다. 그것이 가능한 한 빨리이 대답을 받아 들일 것입니다. g ++가 -pedantic으로 그것을 해결한다는 것에 흥미 롭습니다. 당신이있는 경우 사양 @CodingCat –
말한다 "foo.bar을 <", "바"가 처음 "foo는"의 클래스에보고해야 템플릿인지 여부를 알 수 있습니다. 그리고 거기에 "막대"가 없다면, 전체 표현의 문맥에서 찾아야합니다. 그러나 객체의 클래스에 있는지 여부를 확인하려면 먼저 주변 템플리트가 인스턴스화 될 때까지 대기해야합니다. Clang이 그렇게합니다. GCC는 템플릿이 아니라고 생각합니다. 이것은 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55576의 문제이기도합니다. 그 버그 보고서에서 GCC는 유효한 프로그램을 거부합니다. –
"템플릿"disambiguator의 전체 목적은 컴파일러가 이름이 템플릿인지 결정하는 데 도움이됩니다. 그러나 GCC는 disambiguator를 사용하지 않고, 스스로이 작업을 수행하기로 결정, 따라서 구성원으로 표현의 맥락에서 "GetRef"를 찾습니다. 나는이 GCC 행동이 정확하다고 생각하지 않는다. –