Как правильно проверить (const) перегруженный метод - PullRequest
3 голосов
/ 06 марта 2012

Я сейчас пытаюсь получить следующее для компиляции:

class foo {
};

class bar {
public:
  const foo & to_foo() const {
    return f;
  }

  foo & to_foo() {
    return f;
  }
private:
 foo f;
};

template< typename T, typename Enable = void >
class convert {};

template< typename T >
struct convert< T, typename std::enable_if< std::is_member_function_pointer< decltype( &T::to_foo ) >::value >::type > {

  static const foo & call1( const bar & b ) {
    return b.to_foo();
  }

  static foo & call2( bar & b ) {
    return b.to_foo();
  }
};

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

Есть ли способ обнаружить эту функцию в этом случае?

EDIT

Вот пример для ideone: http://ideone.com/E6saX

Когда один из методов удален, он работает просто отлично: http://ideone.com/iBKoN

Ответы [ 3 ]

1 голос
/ 06 марта 2012

Мне все еще неясно, чего вы пытаетесь достичь. Я предполагаю, что целевой тип (foo) фиксирован, и мы не пытаемся создать полную систему моста.

В этом случае мы можем отказаться от конструкции и просто положиться на выбор перегрузки.

foo const& to_foo(bar const& b) { return b.to_foo(); }
foo& to_foo(bar& b) { return b.to_foo(); }

Работает просто отлично, насколько позволяет перевод. Шаблон не задействован.

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

#include <iostream>
#include <utility>

// Didn't remember where this is implemented, oh well
template <typename T, typename U> struct same_type: std::false_type {};
template <typename T> struct same_type<T, T>: std::true_type {};

// Types to play with
struct Foo {};
struct Bar { Foo _foo; };
struct Bad {};

Foo const& to_foo(Bar const& b) { return b._foo; }
Foo& to_foo(Bar& b) { return b._foo; }

// Checker
template <typename T>
struct ToFoo {
  T const& _crt;
  T& _rt;

  template <typename U>
  static auto to_foo_exists(U const& crt, U& rt) ->
      decltype(to_foo(crt), to_foo(rt), std::true_type());

  static std::false_type to_foo_exists(...);

  // Work around as the following does not seem to work
  // static bool const value = decltype(to_foo_exists(_crt, _rt))::value;
  static bool const value = same_type<
                                decltype(to_foo_exists(_crt, _rt)),
                                std::true_type
                            >::value;
};

// Proof
int main() {
  std::cout << ToFoo<Bar>::value << "\n"; // true
  std::cout << ToFoo<Bad>::value << "\n"; // false
}

Примечание: успешно скомпилировано на Clang 3.0 (с обходом) и gcc 4.5.1 .

0 голосов
/ 06 марта 2012

мой gcc (4.1.0) не поддерживает c ++ 0x, поэтому я удалил часть std :: enable_if. затем он компилируется и работает успешно. увидеть: http://ideone.com/KzasX

спасибо

0 голосов
/ 06 марта 2012

Я пока не знаю много о шаблонах, но, похоже, is_const - это типовая черта, которую вы ищете, чтобы проверить, является ли функция const.

Ссылка здесь

...