메타 프로그래밍을 위해 멤버 함수 포인터를 형식에 저장하고 나중에이를 사용하여 템플릿을 매개 변수화하고 싶습니다.
비유하면 다음은 integer_constant
유형에 int를 저장하는 방법에 대한 작업 예제입니다 .
template< int I >
struct integer_constant {
static constexpr int value = I;
};
template <int I>
struct A {
// (client type, probably does other things with I)
static constexpr int value = I;
};
namespace {
using cStored= integer_constant<42>; // store value
static_assert(cStored::value == 42, "");
// ...
using aUseStored = A<cStored::value>; // use value as template parameter
static_assert(aUseStored::value == 42, "");
}
멤버 함수 포인터로 같은 일을 할 수 있습니까? 그렇지 않다면 왜 안됩니까?
struct S{
void foo() {}
};
typedef void (S::*s_member_fn_type)();
template< s_member_fn_type M >
struct member_fn_constant {
static constexpr s_member_fn_type value = M;
};
template <s_member_fn_type M>
struct A {
// (client type, probably does other things with M)
static constexpr s_member_fn_type value = M;
};
namespace {
using cStored = member_fn_constant<&S::foo>; // store value
// clang is ok with the following line
// gcc 6.2: error: non-constant condition for static assertion
// gcc 6.2: error: '(s_member_fn_type)member_fn_constant<&S::foo>::value' is not a constant expression
static_assert(cStored::value == &S::foo, "");
// following line gives:
// clang 3.9.0 error: non-type template argument is not a pointer to member constant
// gcc 6.2: error: could not convert template argument 'member_fn_constant<&S::foo>::value' to 'void (S::*)()'
using aUseStored = A<cStored::value>; // use value as template parameter
//static_assert(aUseStored ::value == &S::foo, "");
}
다음과 같이 함수 포인터 대신 래퍼 구조체를 전달하여 간접 수준을 추가 할 수 있음을 이해합니다.
template <typename MT>
struct B {
static constexpr s_member_fn_type value = MT::value;
};
namespace {
using bUseStored = B<cStored>;
}
그러나 내 클라이언트 클래스 A
가 이미 멤버 함수 포인터를 사용하도록 정의 된 경우 도움이되지 않습니다 .
C ++ 17 이전 버전에서는 멤버 함수에 대한 포인터가 상수식이 아닙니다.
C ++ 17에서 N4268에 의해 해결 된 상수 표현식 입니다.
Clang에서 C ++ 지원을-std=c++1z
볼 수 있듯이 clang은 clang 3.5에서 지원했습니다.
g ++는 g ++ 6에서 지원했다고 주장했지만 사실이 아닌 것 같습니다 . GCC의 C ++ 표준 지원을 참조하세요.
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다