service_enum_t only works with entrypoint classes - you would have to enumerate playlist_callback_static and call service_query_t() on each pointer to test if it implements the cache interface. Actually, standard_api_create_t which is used in static_api_ptr_t does that for you, so your second line should actually work.
But considering that implementations working with your cache would never want to call playlist_callback methods such as on_items_added() on their own, maybe deriving directly from playlist_callback_static wasn't such a good idea after all.
How about this:
CODE
class NOVTABLE cache : public service_base {
public:
virtual int get_value(t_size playlist) = 0;
FB2K_MAKE_SERVICE_INTERFACE_ENTRYPOINT(cache);
};
Usage would be the same as in your examples, using enumeration or static_api_ptr_t, depending on how many implementations you have.
The implementation would look like this:
CODE
class cache_impl : public cache {
int get_value(t_size playlist);
public:
// Do whatever is necessary to update your cached content.
void on_items_added(t_size p_playlist, t_size p_start, metadb_handle_list_cref p_data, const bit_array & p_selection);
// Implement other playlist_callback methods here.
};
static service_factory_single_transparent_t<cache_impl> g_cache_impl;
With a helper class that implements playlist_callback_static and forwards relevant callbacks to your cache implementation:
CODE
class cache_playlist_callback : public playlist_callback_static {
unsigned get_flags() { return flag_all; }
void on_items_added(t_size p_playlist, t_size p_start, metadb_handle_list_cref p_data, const bit_array & p_selection) { g_cache_impl.on_items_added(p_playlist, p_start, p_data, p_selection); }
// Repeat for other playlist_callback methods. Some may do nothing.
};
// Uncomment when done.
// static service_factory_single_t<cache_playlist_callback> g_cache_playlist_callback;
Hope this helps.