1
我想創建一個回調註冊類tat允許註冊對不同類型的字符串標識符的回調。每個回調都有簽名void function(T val)
,其中T
是不斷變化的類型。variadic模板和mixins的歧義錯誤
我創建了以下基本註冊器類,它將字符串映射到函數。
#include <string>
#include <map>
#include <functional>
#include <cstdint>
#include <iostream>
using namespace std;
template< typename ValueType >
class BasicConfigCallbackRegistrar
{
public:
typedef ValueType value_type;
typedef BasicConfigCallbackRegistrar<value_type> type;
typedef function< void(const value_type) > signature_type;
typedef map< string, signature_type > callback_map_type;
/// @brief constructor
BasicConfigCallbackRegistrar() : callbackMap_()
{
}
/// @brief register a create callback
/// @param nodePath the path identifying the node in config database
/// @param callback the callback to register
type& RegisterCallback(string nodePath, signature_type callback)
{
callbackMap_.insert(make_pair(move(nodePath), callback));
return *this;
}
void MakeCallback(const string& nodePath, value_type val)
{
// no checking assumes item is in map,
// do not do this in production code
auto iter = callbackMap_.find(nodePath);
iter->second(val);
}
private:
callback_map_type callbackMap_; ///< the callback map
};
然後,我使用可變參數模板爲每個我想要支持的類型創建派生類。
template< typename... Types >
class ConfigCallbackRegistrar : public BasicConfigCallbackRegistrar<Types>...
{
public:
/// @brief constructor
ConfigCallbackRegistrar() : BasicConfigCallbackRegistrar<Types>()...
{}
};
這則typedef操作爲:
typedef ConfigCallbackRegistrar< uint32_t, string > CallbackRegistrar;
當我嘗試使用這個類,如下所示:不幸的是,當我嘗試編譯此我得到以下歧義錯誤
struct UintFtor
{
void operator()(uint32_t val)
{
cout << val << "\n";
}
};
struct StringFtor
{
void operator()(string val)
{
cout << val << "\n";
}
};
int main()
{
CallbackRegistrar registrar{};
registrar.RegisterCallback("SomeNode", UintFtor());
registrar.RegisterCallback("SomeNode", StringFtor());
return 0;
}
:
variadic-wrap.cpp: In function ‘int main()’:
variadic-wrap.cpp:87: error: request for member ‘RegisterCallback’ is ambiguous
variadic-wrap.cpp:27: error: candidates are: BasicConfigCallbackRegistrar<ValueType>& BasicConfigCallbackRegistrar<ValueType>::RegisterCallback(std::string, std::function<void(ValueType)>) [with ValueType = std::basic_string<char, std::char_traits<char>, std::allocator<char> >]
variadic-wrap.cpp:27: error: BasicConfigCallbackRegistrar<ValueType>& BasicConfigCallbackRegistrar<ValueType>::RegisterCallback(std::string, std::function<void(ValueType)>) [with ValueType = unsigned int]
variadic-wrap.cpp:88: error: request for member ‘RegisterCallback’ is ambiguous
variadic-wrap.cpp:27: error: candidates are: BasicConfigCallbackRegistrar<ValueType>& BasicConfigCallbackRegistrar<ValueType>::RegisterCallback(std::string, std::function<void(ValueType)>) [with ValueType = std::basic_string<char, std::char_traits<char>, std::allocator<char> >]
variadic-wrap.cpp:27: error: BasicConfigCallbackRegistrar<ValueType>& BasicConfigCallbackRegistrar<ValueType>::RegisterCallback(std::string, std::function<void(ValueType)>) [with ValueType = unsigned int]
調用MakeCallback
需要參數類型value_type
也會產生相同的模糊性錯誤。
如何解決這個問題,而不需要將registrar
轉換爲基類類型?