Мне все еще неясно, чего вы пытаетесь достичь. Я предполагаю, что целевой тип (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 .