根据 lambda 的结果重载
Overload depending on result of lambda
我有一个 class 喜欢:
class foo
{
EventManager<LRESULT(UINT, WPARAM, LPARAM)> Events;
template<typename T>
void addListener(int e, T&& lambda) { events.add(e, lambda); }
};
但是,我需要接受两种类型的 lambda。签名之一:
[&](UINT, WPARAM, LPARAM) -> LRESULT {}
和一个签名:[&](UINT, WPARAM, LPARAM) -> void {}
.
所以我想确定 lambdas 的 return 类型..
我试过类似的方法:
template<typename T>
void addListener(int e, T&& listener)
{
if (std::is_void<decltype(listener(0, 0, 0))>::value)
{
Events.Subscribe(e, [&](UINT msg, WPARAM wp, LPARAM lp) -> LRESULT {
listener(msg, wp, lp);
return DefWindowProcW(this->Handle(), msg, wp, lp);
});
}
Events.Subscribe(e, [&](UINT msg, WPARAM wp, LPARAM lp) -> LRESULT {
std::function<LRESULT()> func = std::bind(listener, msg, wp, lp);
return func();
});
}
我还尝试将函数声明为具有以下签名的模板:
template<typename T, typename = typename std::enable_if<std::is_void<typename std::result_of<T(UINT, WPARAM, LPARAM)>::type>::value>::type>
让它过载,但它也不起作用..
有什么想法我可以做什么而不必创建两种方法(每个签名一个)?
选项#1
将调用分派到适当的重载:
#include <functional>
#include <type_traits>
#include <utility>
class foo
{
public:
template <typename T>
void addListener(int e, T&& listener)
{
addListener(e, std::forward<T>(listener), std::is_void<decltype(listener(0, 0, 0))>{});
}
private:
EventManager<LRESULT(UINT, WPARAM, LPARAM)> Events;
template <typename T>
void addListener(int e, T&& listener, std::true_type)
{
Events.Subscribe(e, [=](UINT msg, WPARAM wp, LPARAM lp) -> LRESULT {
listener(msg, wp, lp);
return DefWindowProcW(this->Handle(), msg, wp, lp);
});
}
template <typename T>
void addListener(int e, T&& listener, std::false_type)
{
Events.Subscribe(e, [=](UINT msg, WPARAM wp, LPARAM lp) -> LRESULT {
std::function<LRESULT()> func = std::bind(listener, msg, wp, lp);
return func();
});
}
};
选项#2
添加带有 SFINAE 条件的重载(如果您想在第二个重载中的模板参数列表中隐藏 enable_if
,则需要一个虚拟类型模板参数 typename = void
,以使函数模板' 不同的声明):
#include <functional>
#include <type_traits>
class foo
{
public:
template <typename T,
typename = typename std::enable_if<std::is_void<typename std::result_of<T(UINT, WPARAM, LPARAM)>::type>::value>::type>
void addListener(int e, T&& listener)
{
Events.Subscribe(e, [=](UINT msg, WPARAM wp, LPARAM lp) -> LRESULT {
listener(msg, wp, lp);
return DefWindowProcW(this->Handle(), msg, wp, lp);
});
}
template <typename T,
typename = typename std::enable_if<!std::is_void<typename std::result_of<T(UINT, WPARAM, LPARAM)>::type>::value>::type,
typename = void>
void addListener(int e, T&& listener)
{
Events.Subscribe(e, [=](UINT msg, WPARAM wp, LPARAM lp) -> LRESULT {
std::function<LRESULT()> func = std::bind(listener, msg, wp, lp);
return func();
});
}
private:
EventManager<LRESULT(UINT, WPARAM, LPARAM)> Events;
};
选项#3
使用带有 decltype()
说明符的尾随 return 类型来 enable/disable 重载:
#include <functional>
#include <type_traits>
#include <utility>
class foo
{
public:
template <typename T>
auto addListener(int e, T&& listener)
-> typename std::enable_if<std::is_void<decltype(std::forward<T>(listener)(0, 0, 0))>{}>::type
{
Events.Subscribe(e, [=](UINT msg, WPARAM wp, LPARAM lp) -> LRESULT {
listener(msg, wp, lp);
return DefWindowProcW(this->Handle(), msg, wp, lp);
});
}
template <typename T>
auto addListener(int e, T&& listener)
-> typename std::enable_if<!std::is_void<decltype(std::forward<T>(listener)(0, 0, 0))>{}>::type
{
Events.Subscribe(e, [=](UINT msg, WPARAM wp, LPARAM lp) -> LRESULT {
std::function<LRESULT()> func = std::bind(listener, msg, wp, lp);
return func();
});
}
private:
EventManager<LRESULT(UINT, WPARAM, LPARAM)> Events;
};
我有一个 class 喜欢:
class foo
{
EventManager<LRESULT(UINT, WPARAM, LPARAM)> Events;
template<typename T>
void addListener(int e, T&& lambda) { events.add(e, lambda); }
};
但是,我需要接受两种类型的 lambda。签名之一:
[&](UINT, WPARAM, LPARAM) -> LRESULT {}
和一个签名:[&](UINT, WPARAM, LPARAM) -> void {}
.
所以我想确定 lambdas 的 return 类型..
我试过类似的方法:
template<typename T>
void addListener(int e, T&& listener)
{
if (std::is_void<decltype(listener(0, 0, 0))>::value)
{
Events.Subscribe(e, [&](UINT msg, WPARAM wp, LPARAM lp) -> LRESULT {
listener(msg, wp, lp);
return DefWindowProcW(this->Handle(), msg, wp, lp);
});
}
Events.Subscribe(e, [&](UINT msg, WPARAM wp, LPARAM lp) -> LRESULT {
std::function<LRESULT()> func = std::bind(listener, msg, wp, lp);
return func();
});
}
我还尝试将函数声明为具有以下签名的模板:
template<typename T, typename = typename std::enable_if<std::is_void<typename std::result_of<T(UINT, WPARAM, LPARAM)>::type>::value>::type>
让它过载,但它也不起作用..
有什么想法我可以做什么而不必创建两种方法(每个签名一个)?
选项#1
将调用分派到适当的重载:
#include <functional>
#include <type_traits>
#include <utility>
class foo
{
public:
template <typename T>
void addListener(int e, T&& listener)
{
addListener(e, std::forward<T>(listener), std::is_void<decltype(listener(0, 0, 0))>{});
}
private:
EventManager<LRESULT(UINT, WPARAM, LPARAM)> Events;
template <typename T>
void addListener(int e, T&& listener, std::true_type)
{
Events.Subscribe(e, [=](UINT msg, WPARAM wp, LPARAM lp) -> LRESULT {
listener(msg, wp, lp);
return DefWindowProcW(this->Handle(), msg, wp, lp);
});
}
template <typename T>
void addListener(int e, T&& listener, std::false_type)
{
Events.Subscribe(e, [=](UINT msg, WPARAM wp, LPARAM lp) -> LRESULT {
std::function<LRESULT()> func = std::bind(listener, msg, wp, lp);
return func();
});
}
};
选项#2
添加带有 SFINAE 条件的重载(如果您想在第二个重载中的模板参数列表中隐藏 enable_if
,则需要一个虚拟类型模板参数 typename = void
,以使函数模板' 不同的声明):
#include <functional>
#include <type_traits>
class foo
{
public:
template <typename T,
typename = typename std::enable_if<std::is_void<typename std::result_of<T(UINT, WPARAM, LPARAM)>::type>::value>::type>
void addListener(int e, T&& listener)
{
Events.Subscribe(e, [=](UINT msg, WPARAM wp, LPARAM lp) -> LRESULT {
listener(msg, wp, lp);
return DefWindowProcW(this->Handle(), msg, wp, lp);
});
}
template <typename T,
typename = typename std::enable_if<!std::is_void<typename std::result_of<T(UINT, WPARAM, LPARAM)>::type>::value>::type,
typename = void>
void addListener(int e, T&& listener)
{
Events.Subscribe(e, [=](UINT msg, WPARAM wp, LPARAM lp) -> LRESULT {
std::function<LRESULT()> func = std::bind(listener, msg, wp, lp);
return func();
});
}
private:
EventManager<LRESULT(UINT, WPARAM, LPARAM)> Events;
};
选项#3
使用带有 decltype()
说明符的尾随 return 类型来 enable/disable 重载:
#include <functional>
#include <type_traits>
#include <utility>
class foo
{
public:
template <typename T>
auto addListener(int e, T&& listener)
-> typename std::enable_if<std::is_void<decltype(std::forward<T>(listener)(0, 0, 0))>{}>::type
{
Events.Subscribe(e, [=](UINT msg, WPARAM wp, LPARAM lp) -> LRESULT {
listener(msg, wp, lp);
return DefWindowProcW(this->Handle(), msg, wp, lp);
});
}
template <typename T>
auto addListener(int e, T&& listener)
-> typename std::enable_if<!std::is_void<decltype(std::forward<T>(listener)(0, 0, 0))>{}>::type
{
Events.Subscribe(e, [=](UINT msg, WPARAM wp, LPARAM lp) -> LRESULT {
std::function<LRESULT()> func = std::bind(listener, msg, wp, lp);
return func();
});
}
private:
EventManager<LRESULT(UINT, WPARAM, LPARAM)> Events;
};