CS253: Software Development with C++

Spring 2023

Duck Typing

Show Lecture.DuckTyping as a slide show.

CS253 Duck Typing

🦆 🦆 🦆 The Saying 🦆 🦆 🦆

If it walks like a duck,

  and quacks like a duck,   then it’s a duck.

This saying stresses common sense over formal definition. If I were doing 200mph on I-25 in Luke Skywalker’s speeder, I wouldn’t get far telling a state trooper that it’s “not a car”. The law would probably view it as a car, even without wheels.

Rules for Rulers

Rules for Containers

Enforcement

Example

A vector requires that its stored type be copyable, both via copy ctor and assignment operator. You can have a vector<string>, because strings are copyable:

string now = "2024-11-21T09:25:02"; // ISO 8601, baby!
vector<string> v;
v.push_back(now);
cout << v.front() << '\n';
2024-11-21T09:25:02

Example

How about a non-copyable class?

vector<istream> v;
cout << "size=" << v.size();
size=0

That worked fine! Well, we might try adding something to the vector

vector<istream> v;
v.push_back(cin);  // 🦡
In file included from /usr/local/gcc/11.2.0/include/c++/11.2.0/x86_64-pc-linux-gnu/bits/c++allocator.h:33,
                 from /usr/local/gcc/11.2.0/include/c++/11.2.0/bits/allocator.h:46,
                 from /usr/local/gcc/11.2.0/include/c++/11.2.0/string:41,
                 from /usr/local/gcc/11.2.0/include/c++/11.2.0/bits/locale_classes.h:40,
                 from /usr/local/gcc/11.2.0/include/c++/11.2.0/bits/ios_base.h:41,
                 from /usr/local/gcc/11.2.0/include/c++/11.2.0/ios:42,
                 from /s/bach/a/class/cs000/public_html/pmwiki/cookbook/c++-includes.h:5,
                 from <command-line>:
/usr/local/gcc/11.2.0/include/c++/11.2.0/ext/new_allocator.h: In instantiation of ‘void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = std::basic_istream<char>; _Args = {const std::basic_istream<char, std::char_traits<char> >&}; _Tp = std::basic_istream<char>]’:
/usr/local/gcc/11.2.0/include/c++/11.2.0/bits/alloc_traits.h:512:   required from ‘static void std::allocator_traits<std::allocator<_CharT> >::construct(std::allocator_traits<std::allocator<_CharT> >::allocator_type&, _Up*, _Args&& ...) [with _Up = std::basic_istream<char>; _Args = {const std::basic_istream<char, std::char_traits<char> >&}; _Tp = std::basic_istream<char>; std::allocator_traits<std::allocator<_CharT> >::allocator_type = std::allocator<std::basic_istream<char> >]’
/usr/local/gcc/11.2.0/include/c++/11.2.0/bits/stl_vector.h:1192:   required from ‘void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = std::basic_istream<char>; _Alloc = std::allocator<std::basic_istream<char> >; std::vector<_Tp, _Alloc>::value_type = std::basic_istream<char>]’
c.cc:2:   required from here
/usr/local/gcc/11.2.0/include/c++/11.2.0/ext/new_allocator.h:162: error: use of 
   deleted function ‘std::basic_istream<_CharT, _Traits>::basic_istream(const 
   std::basic_istream<_CharT, _Traits>&) [with _CharT = char; _Traits = 
   std::char_traits<char>]’

How enforcement “works”