SFINAE 的问题
troubles with SFINAE
我试图重载运算符 - 以便它对其参数应用集合差异。因为我无法弄清楚如何将它限制为仅用于 STL 容器(因为如果我不这样做,它会覆盖每个运算符 - 看起来),我试图将它限制为仅设置和矢量,因为我会与那些一起使用二。
这是我的代码:
#define RANGE(x) (x).begin(), (x).end()
template<class T>
struct is_STL_container
{
static const bool value = false;
};
template<class T, typename alloc>
struct is_STL_container<std::vector<T, alloc>>
{
static const bool value = true;
};
template<class T, class comp, typename alloc>
struct is_STL_container<std::set<T, comp, alloc>>
{
static const bool value = true;
};
template <class T1, class T2,
class std::enable_if<is_STL_container<T1>::value && is_STL_container<T2>::value, T1>::type>
T1 operator - (const T1 &l, const T2 &r)
{
assert(typeid(T1::value_type) == typeid(T2::value_type));
std::vector<T1::value_type> result;
std::set_difference(RANGE(l), RANGE(r), std::back_inserter(result));
return T1(RANGE(result));
}
但是当我尝试编译我的程序时,出现以下错误:
Error 2 error C1903: unable to recover from previous error(s); stopping compilation C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\algorithm 3071 1 TrafficLight
Error 1 error C2893: Failed to specialize function template 'unknown-type std::less<void>::operator ()(_Ty1 &&,_Ty2 &&) const' C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\algorithm 3071 1 TrafficLight
我想不通这个问题
我正在使用 VS2013
最好的问候
乌作
std::enable_if
是一个返回类型的元函数(默认为 void)。
因此,您的主要 operator-
语句格式错误。
您必须将模板 class
参数更改为如下所示
class = typename std::enable_if_t<is_STL_container<T1>::value &&
is_STL_container<T2>::value>
或者这样:
class = typename std::enable_if<is_STL_container<T1>::value &&
is_STL_container<T2>::value>::type
您可以找到固定程序here。
考虑这个定义
template <class T1, class T2, class int> int operator- ...
这显然是不正确的,对吧?但是你只写了稍微复杂一点的版本。
你需要什么
template <class T1, class T2>
typename std::enable_if<whatever>::type
operator- ...
您的代码存在一些语法错误。以下示例有效。
注: 下面的 operator-
是基于 T
而不是 T1
和 T2
的模板,因为我不是确定你真的想让 operator-
在使用不同类型的向量时工作,例如std::vector<int>
和 std::vector<double>
.
示例代码
#include <algorithm>
#include <iostream>
#include <set>
#include <vector>
#define RANGE(x) (x).begin(), (x).end()
template<class T>
struct is_STL_container
{
static const bool value = false;
};
template<class T, typename alloc>
struct is_STL_container<std::vector<T, alloc>>
{
static const bool value = true;
};
template<class T, class comp, typename alloc>
struct is_STL_container<std::set<T, comp, alloc>>
{
static const bool value = true;
};
template <class T>
typename std::enable_if<is_STL_container<T>::value && is_STL_container<T>::value, T>::type
operator-(const T &l, const T &r)
{
T result;
std::set_difference(RANGE(l), RANGE(r), std::back_inserter(result));
return result;
}
int main()
{
std::vector<int> a = { 1, 2, 3, 4, 5 };
std::vector<int> b = { 2, 3, 4 };
std::vector<int> r = a - b;
for (const auto& v : r)
{
std::cout << v << " ";
}
return 0;
}
示例输出
1 5
编辑 1
注意: 正如@StoryTeller 在评论中指出的那样,仅在 T
上模板化 operator-
会阻止 [=14= 的有效使用] 在 std::vector<int>
和 std::set<int>
之间(正如 OP 所尝试的那样)。以下代码使用 T1
和 T2
来解决此问题。
示例代码
#include <algorithm>
#include <cassert>
#include <iostream>
#include <set>
#include <typeinfo>
#include <vector>
#define RANGE(x) (x).begin(), (x).end()
template<class T>
struct is_STL_container
{
static const bool value = false;
};
template<class T, typename alloc>
struct is_STL_container<std::vector<T, alloc>>
{
static const bool value = true;
};
template<class T, class comp, typename alloc>
struct is_STL_container<std::set<T, comp, alloc>>
{
static const bool value = true;
};
template <class T1, class T2>
typename std::enable_if<is_STL_container<T1>::value && is_STL_container<T2>::value, T1>::type
operator-(const T1 &l, const T2 &r)
{
assert(typeid(typename T1::value_type) == typeid(typename T2::value_type));
T1 result;
std::set_difference(RANGE(l), RANGE(r), std::back_inserter(result));
return result;
}
int main()
{
std::vector<int> a = { 1, 2, 3, 4, 5 };
std::vector<int> b = { 2, 3, 4 };
std::set<int> c = { 2, 3, 4 };
std::vector<int> r = a - b;
for (const auto& v : r)
{
std::cout << v << " ";
}
std::cout << "\n";
r = a - c;
for (const auto& v : r)
{
std::cout << v << " ";
}
return 0;
}
示例输出
1 5
1 5
我试图重载运算符 - 以便它对其参数应用集合差异。因为我无法弄清楚如何将它限制为仅用于 STL 容器(因为如果我不这样做,它会覆盖每个运算符 - 看起来),我试图将它限制为仅设置和矢量,因为我会与那些一起使用二。 这是我的代码:
#define RANGE(x) (x).begin(), (x).end()
template<class T>
struct is_STL_container
{
static const bool value = false;
};
template<class T, typename alloc>
struct is_STL_container<std::vector<T, alloc>>
{
static const bool value = true;
};
template<class T, class comp, typename alloc>
struct is_STL_container<std::set<T, comp, alloc>>
{
static const bool value = true;
};
template <class T1, class T2,
class std::enable_if<is_STL_container<T1>::value && is_STL_container<T2>::value, T1>::type>
T1 operator - (const T1 &l, const T2 &r)
{
assert(typeid(T1::value_type) == typeid(T2::value_type));
std::vector<T1::value_type> result;
std::set_difference(RANGE(l), RANGE(r), std::back_inserter(result));
return T1(RANGE(result));
}
但是当我尝试编译我的程序时,出现以下错误:
Error 2 error C1903: unable to recover from previous error(s); stopping compilation C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\algorithm 3071 1 TrafficLight
Error 1 error C2893: Failed to specialize function template 'unknown-type std::less<void>::operator ()(_Ty1 &&,_Ty2 &&) const' C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\algorithm 3071 1 TrafficLight
我想不通这个问题 我正在使用 VS2013
最好的问候 乌作
std::enable_if
是一个返回类型的元函数(默认为 void)。
因此,您的主要 operator-
语句格式错误。
您必须将模板 class
参数更改为如下所示
class = typename std::enable_if_t<is_STL_container<T1>::value &&
is_STL_container<T2>::value>
或者这样:
class = typename std::enable_if<is_STL_container<T1>::value &&
is_STL_container<T2>::value>::type
您可以找到固定程序here。
考虑这个定义
template <class T1, class T2, class int> int operator- ...
这显然是不正确的,对吧?但是你只写了稍微复杂一点的版本。
你需要什么
template <class T1, class T2>
typename std::enable_if<whatever>::type
operator- ...
您的代码存在一些语法错误。以下示例有效。
注: 下面的 operator-
是基于 T
而不是 T1
和 T2
的模板,因为我不是确定你真的想让 operator-
在使用不同类型的向量时工作,例如std::vector<int>
和 std::vector<double>
.
示例代码
#include <algorithm>
#include <iostream>
#include <set>
#include <vector>
#define RANGE(x) (x).begin(), (x).end()
template<class T>
struct is_STL_container
{
static const bool value = false;
};
template<class T, typename alloc>
struct is_STL_container<std::vector<T, alloc>>
{
static const bool value = true;
};
template<class T, class comp, typename alloc>
struct is_STL_container<std::set<T, comp, alloc>>
{
static const bool value = true;
};
template <class T>
typename std::enable_if<is_STL_container<T>::value && is_STL_container<T>::value, T>::type
operator-(const T &l, const T &r)
{
T result;
std::set_difference(RANGE(l), RANGE(r), std::back_inserter(result));
return result;
}
int main()
{
std::vector<int> a = { 1, 2, 3, 4, 5 };
std::vector<int> b = { 2, 3, 4 };
std::vector<int> r = a - b;
for (const auto& v : r)
{
std::cout << v << " ";
}
return 0;
}
示例输出
1 5
编辑 1
注意: 正如@StoryTeller 在评论中指出的那样,仅在 T
上模板化 operator-
会阻止 [=14= 的有效使用] 在 std::vector<int>
和 std::set<int>
之间(正如 OP 所尝试的那样)。以下代码使用 T1
和 T2
来解决此问题。
示例代码
#include <algorithm>
#include <cassert>
#include <iostream>
#include <set>
#include <typeinfo>
#include <vector>
#define RANGE(x) (x).begin(), (x).end()
template<class T>
struct is_STL_container
{
static const bool value = false;
};
template<class T, typename alloc>
struct is_STL_container<std::vector<T, alloc>>
{
static const bool value = true;
};
template<class T, class comp, typename alloc>
struct is_STL_container<std::set<T, comp, alloc>>
{
static const bool value = true;
};
template <class T1, class T2>
typename std::enable_if<is_STL_container<T1>::value && is_STL_container<T2>::value, T1>::type
operator-(const T1 &l, const T2 &r)
{
assert(typeid(typename T1::value_type) == typeid(typename T2::value_type));
T1 result;
std::set_difference(RANGE(l), RANGE(r), std::back_inserter(result));
return result;
}
int main()
{
std::vector<int> a = { 1, 2, 3, 4, 5 };
std::vector<int> b = { 2, 3, 4 };
std::set<int> c = { 2, 3, 4 };
std::vector<int> r = a - b;
for (const auto& v : r)
{
std::cout << v << " ";
}
std::cout << "\n";
r = a - c;
for (const auto& v : r)
{
std::cout << v << " ";
}
return 0;
}
示例输出
1 5
1 5