Здесь много чего нужно исправить.Для начала, ваш основной size_t res = get_size<v>;
не будет работать, потому что вы не можете иметь v
в качестве аргумента шаблона, я предполагаю, что вместо этого он должен был get_size(v)
.
В get_size
у вас есть это
if (has_size<T>::value) {
res = t.size();
} else {
res = t.size;
}
Это не сработает, потому что, хотя используется только один, компилятор видит, что вы делаете и t.size
, и t.size()
.Я вижу, ваш вопрос помечен тегом c ++ 11, поэтому я предоставлю ответ на языке c ++ 11.
Сначала я собираюсь создать несколько очень простых классов, один с функцией-членом, а другой сэлемент данных
// using distinc values 7 and 3 to differentiate easily later
struct SizeData {
std::size_t size = 7;
};
struct SizeFunc {
std::size_t size() const { return 3; };
};
Я также напишу базовый void_t
для метапрограммирования и использую очень стандартный современный подход к метапрограммированию, чтобы проверить, имеет ли данный тип .size()
функция-член.(похоже, что техника, которую вы пытаетесь устареть).
template <typename>
using void_type = void;
template <typename T, typename = void>
struct HasSizeFunc : std::false_type { };
template <typename T>
struct HasSizeFunc<T, void_type<decltype(std::declval<const T&>().size())>>
: std::true_type { };
Я могу очень легко использовать это в основной сети, чтобы проверить, имеет ли что-то .size()
или нет
int main() {
std::cout << "SizeFunc: " << HasSizeFunc<SizeFunc>::value << '\n';
std::cout << "SizeData: " << HasSizeFunc<SizeData>::value << '\n';
}
Но теперь для функции get_size()
.Как я уже говорил ранее, ваш if / else не будет работать, потому что обе ветви не компилируются (if constexpr
работает, но не доступен в c ++ 11).Таким образом, вместо этого вы можете сделать то, что называется «диспетчеризацией тегов», чтобы решить, какую перегрузку функции вызывать для вызова правильного .size
// std::size_t may not be right for every type. leaving it for simplicity.
template <typename T>
std::size_t get_size_impl(T t, std::true_type) {
return t.size();
}
template <typename T>
std::size_t get_size_impl(T t, std::false_type) {
return t.size;
}
template <typename T>
std::size_t get_size(T t) { // note, this should probably be a const reference
// second argument used to select an overload of get_size_impl
return get_size_impl(t, HasSizeFunc<T>{});
}
И использовать ее:
int main() {
SizeFunc sf;
std::cout << "SizeFunc: " << get_size(sf) << '\n';
SizeData sd;
std::cout << "SizeData: " << get_size(sd) << '\n';
}
нажмите здесь, чтобы увидеть весь код в одном живом примере .Я рекомендую посмотреть эти разговоры cppcon , чтобы узнать больше.
Кроме того, здесь - это то, что я бы сделал в c ++ 17