应用具有通用参考的 SFINAE 模式
Applying SFINAE pattern with universal reference
我有以下代码:
#include <utility>
#include <iostream>
#include <queue>
#include <functional>
#include <stdio.h>
#include <future>
class Runner {
public:
virtual void run() = 0;
virtual ~Runner() {
}
};
class Command: public Runner {
public:
Command() {
std::cout << "constructor" << std::endl;
}
virtual void run() {
}
};
#define EXTEND(T, F) , typename = typename std::enable_if<std::is_base_of<F, typename std::decay<T>::type>::value, typename std::decay<T>::type>::type
#define NOT_EXTEND(T, F) , typename = typename std::enable_if<!std::is_base_of<F, typename std::decay<T>::type>::value, typename std::decay<T>::type>::type
class Executor {
private:
std::queue<std::function<void(void)> > q;
public:
template<class T EXTEND(T, Runner)>
void push(T&& toBepushed) {
q.push(
std::bind(&std::decay<T>::type::run,
std::forward<T>(toBepushed)));
}
template<typename T NOT_EXTEND(T, Runner)>
void push(T&& toBepushed) {
q.push(std::forward<T>(toBepushed));
}
void perform() {
std::function<void(void)>&& f = std::move(q.front());
f();
}
};
int main() {
Executor b;
Command c;
b.push(c);
b.perform();
return 0;
}
编译时出现以下错误:
g++ -std=c++0x -O2 -g3 -Wall -c -fmessage-length=0 -MMD -MP
-MF"main.d" -MT"main.o" -o "main.o" "../main.cpp" ../main.cpp:45:7: error: ‘template void Bar::push(T&&)’ cannot be
overloaded void push(T&& toBepushed) {
^~~~ ../main.cpp:39:7: error: with ‘template void Bar::push(T&&)’ void push(T&& toBepushed) {
^~~~ make: *** [subdir.mk:20: main.o] Error 1
我正在尝试应用 SFINAE,以便根据使用的类型应用推送方法。如何解决?
默认参数不是模板参数列表的一部分,因此您的两个 push
具有相同的模板参数列表,这会导致重新声明。
这是 typename = std::enable_if_t<...>
方法的典型缺点。相反,您应该使用 std::enable_if_t<..., int> = 0
方法。
改为:
#define EXTEND(T, F) , typename std::enable_if<std::is_base_of<F, typename std::decay<T>::type>::value, int>::type = 0
#define NOT_EXTEND(T, F) , typename std::enable_if<!std::is_base_of<F, typename std::decay<T>::type>::value, int>::type = 0
我有以下代码:
#include <utility>
#include <iostream>
#include <queue>
#include <functional>
#include <stdio.h>
#include <future>
class Runner {
public:
virtual void run() = 0;
virtual ~Runner() {
}
};
class Command: public Runner {
public:
Command() {
std::cout << "constructor" << std::endl;
}
virtual void run() {
}
};
#define EXTEND(T, F) , typename = typename std::enable_if<std::is_base_of<F, typename std::decay<T>::type>::value, typename std::decay<T>::type>::type
#define NOT_EXTEND(T, F) , typename = typename std::enable_if<!std::is_base_of<F, typename std::decay<T>::type>::value, typename std::decay<T>::type>::type
class Executor {
private:
std::queue<std::function<void(void)> > q;
public:
template<class T EXTEND(T, Runner)>
void push(T&& toBepushed) {
q.push(
std::bind(&std::decay<T>::type::run,
std::forward<T>(toBepushed)));
}
template<typename T NOT_EXTEND(T, Runner)>
void push(T&& toBepushed) {
q.push(std::forward<T>(toBepushed));
}
void perform() {
std::function<void(void)>&& f = std::move(q.front());
f();
}
};
int main() {
Executor b;
Command c;
b.push(c);
b.perform();
return 0;
}
编译时出现以下错误:
g++ -std=c++0x -O2 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"main.d" -MT"main.o" -o "main.o" "../main.cpp" ../main.cpp:45:7: error: ‘template void Bar::push(T&&)’ cannot be overloaded void push(T&& toBepushed) { ^~~~ ../main.cpp:39:7: error: with ‘template void Bar::push(T&&)’ void push(T&& toBepushed) { ^~~~ make: *** [subdir.mk:20: main.o] Error 1
我正在尝试应用 SFINAE,以便根据使用的类型应用推送方法。如何解决?
默认参数不是模板参数列表的一部分,因此您的两个 push
具有相同的模板参数列表,这会导致重新声明。
这是 typename = std::enable_if_t<...>
方法的典型缺点。相反,您应该使用 std::enable_if_t<..., int> = 0
方法。
改为:
#define EXTEND(T, F) , typename std::enable_if<std::is_base_of<F, typename std::decay<T>::type>::value, int>::type = 0
#define NOT_EXTEND(T, F) , typename std::enable_if<!std::is_base_of<F, typename std::decay<T>::type>::value, int>::type = 0