Почему SFINAE приводит к ошибке компилятора там, где он должен был работать? - PullRequest
3 голосов
/ 05 июля 2011

Я пытался реализовать метапрограмму, которая находит, является ли данный тип указателя const или нет. т.е.

  • is_const<TYPE*>::value должно быть false
  • is_const<const TYPE*>::value должно быть true

Ниже приведен код:

template<class TYPE>
struct is_const
{
  typedef char yes[3];
  template<typename T>
  struct Perform
  {
    static yes& check (const T*&);
    static char check (T*&);
  };  

  TYPE it; 
  enum { value = (sizeof(Perform<TYPE>::check(it)) == sizeof(yes)) };  
};

А сообщения об ошибках компилятора:

In instantiation of ‘is_const<int*>’:
instantiated from here
error: no matching function for call to ‘is_const<int*>::Perform<int*>::check(int*&)’
note: candidates are: static char (& is_const<TYPE>::Perform<T>::check(const T*&))[3] [with T = int*, TYPE = int*]
note: static char is_const<TYPE>::Perform<T>::check(T*&) [with T = int*, TYPE = int*]

Мой фокус сместился на сообщение об ошибке. Если вы видите последнюю строку:

note: static char is_const<TYPE>::Perform<T>::check(T*&) [with T = int*, TYPE = int*]

Если мы действительно заменим T = int* и TYPE = int*, тогда оно действительно должно соответствовать соответствующей функции (char check()). Я хочу знать, что здесь происходит не так.

Ответы [ 3 ]

9 голосов
/ 05 июля 2011

Почему так круто? Как насчет прямой черты класса:

#include <functional>

template <typename T> struct is_const_ptr : std::false_type { };
template <typename T> struct is_const_ptr<const T *> : std::true_type { };

struct Foo {};

int main()
{
  std::cout << is_const_ptr<Foo*>::value << is_const_ptr<const Foo*>::value << std::endl;
}
1 голос
/ 05 июля 2011

В вашем коде две вещи неправильные.

Во-первых, следующее

static yes& check (const T*&);
static char check (T*&);

должно быть изменено на

static yes& check (const T&);
static char check (T&);

В секунду, it член должен быть static

static TYPE it;

или просто передать ((TYPE)0) в вашу функцию проверки.Нет необходимости члена.

1 голос
/ 05 июля 2011

Вот ваша проблема:

static yes& check (const T*&);
static char check (T*&);

Когда вы создаете экземпляр is_const<int*>, определения ваших функций расширяются до:

static yes& check (const int**&);
static char check (int**&);

Однако, ваш временный элемент (TYPE it) имеет тип int*, как вы указали. Вам нужно изменить сигнатуры функций check, чтобы удалить указатель указателя, например:

static yes& check (const T&);
static char check (T&);
...