Есть указатель на черты члена или что-то вроде этого? - PullRequest
5 голосов
/ 16 декабря 2009

На основании другой мой вопрос .

Рассмотрим следующий код

template<typename T, int N>
struct A {
  typedef T value_type; // save T to value_type
  static const int size = N; // save N to size
};

Смотри, я могу использовать value_type и size в качестве параметра шаблона.

typedef A<int, 2> A1;
typedef A<A1::value_type, A1::size + 3> A2;  // OK,  A2 is A<int,5>

Теперь я хочу сделать то же самое с указателем на член:

struct Foo {
    int m;
    int r;
};

template<int Foo::*Mem>
struct B {
   static int Foo::* const mp;
};

template<int Foo::*Mem>
int Foo::* const B<Mem>::mp = Mem; // Save pointer to member

Но я получаю ошибку.

typedef B<&Foo::m> B1;
typedef B<B1::mp>  B2;  // DOES NOT WORK

Как заставить работать последнюю строку? Или как получить похожий результат?

Примечание. Я знаю, что это не работает. Никаких ссылок на C ++ Standard не требуется. Мне нужен обходной путь.

Ответы [ 4 ]

1 голос
/ 16 декабря 2009

Не должно работать в соответствии со стандартом C ++ 5.19 / 2:

Другие выражения считаются константными выражениями только для целей инициализации нелокального статического объекта (3.6.2). Такие константные выражения должны принимать одно из следующих значений:
- значение нулевого указателя (4.10),
- значение указателя нулевого элемента (4.11),
- выражение арифметической константы,
- адресное константное выражение,
- выражение справочной константы,
- выражение константы адреса для полного типа объекта, плюс или минус целочисленное выражение константы,
или
- указатель на постоянное выражение члена .

Это не ответ на первоначальный вопрос, но это ответ на это неправильное утверждение.

0 голосов
/ 10 мая 2016

Я с удивлением обнаружил, что такого не существует. По крайней мере, в ожидаемых местах, например:

Здесь ничего нет http://www.boost.org/doc/libs/1_60_0/libs/type_traits/doc/html/index.html ни рядом http://en.cppreference.com/w/cpp/types/is_member_pointer

Исходя из этого http://www.boost.org/doc/libs/1_60_0/libs/type_traits/doc/html/boost_typetraits/reference/function_traits.html и этого http://en.cppreference.com/w/cpp/types/is_member_pointer нетрудно накатить свой собственный.

#include<type_traits> // std::is_pointer_member

template<class MP> struct member_pointer_traits_helper;

template< class T, class U >
struct member_pointer_traits_helper<T U::*>{
    using class_type = U;
    using declaration_type = T;
};

template< class MP >
struct member_pointer_traits : 
member_pointer_traits_helper<typename std::remove_cv<MP>::type> {};

struct B{
    int b;
};

int main(){
    using std::same;

    static_assert(std::is_member_pointer<int B::*>::value == true, "");
    static_assert(is_same<member_pointer_traits<int B::*>::class_type, B>{}, "");
    static_assert(is_same<member_pointer_traits<int B::*>::declaration_type, int>{}, "");
    static_assert(is_same<member_pointer_traits<decltype(&B::b)>::declaration_type, int>{}, "");
//  static_assert(is_same<member_pointer_traits<double>::class_type, B>{}, ""); // error
}

Я не уверен, что имена являются оптимальными. Также при применении к указателю, не являющемуся членом, это приведет к ошибке компилятора (этот дизайн скопирован из http://www.boost.org/doc/libs/1_60_0/libs/type_traits/doc/html/boost_typetraits/reference/function_traits.html),, другой альтернативой может быть возвращение типа void (который, очевидно, является ошибочным возвратом, поскольку void не может быть класс или тип члена.)

(с некоторыми небольшими изменениями его можно использовать с C ++ 98, с C ++ 11 для большей ясности.)

0 голосов
/ 17 декабря 2009

Не совсем ответ, но прямой доступ к Mem работает?

т.е. B1 :: Mem вместо B1 :: mp.

Я почти уверен, что стандарт не допускает этого, поскольку мы обычно печатаем имя шаблона def, когда это тип, а не обращаемся к нему напрямую, но технически это может быть разрешено (не уверен, что это будет означать). Там, где ваше решение, вероятно, не будет работать, поскольку оно требует инициализации статического члена, который выполняется во время выполнения (исправьте меня, если я ошибаюсь), поэтому к нему нельзя получить доступ во время компиляции, как вы хотите.

Возможно, вы могли бы попытаться дать нам более полную картину того, что вы пытаетесь сделать с вашим классом черт / политики, чтобы увидеть, возможен ли подходящий обходной путь.

0 голосов
/ 16 декабря 2009

Майк прав, что он должен скомпилироваться. Это ошибка в VS.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...