首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SFINAE的麻烦

SFINAE的麻烦
EN

Stack Overflow用户
提问于 2016-02-03 16:50:44
回答 3查看 106关注 0票数 0

我试图使操作符过载,以便它对其参数应用set差分。由于我无法知道如何将其仅限于STL容器(因为如果我不这样做,它将覆盖每个操作符--似乎是这样),所以我试图将它限制在设置和向量上,因为我会将它与这两个操作一起使用。这是我的代码:

代码语言:javascript
复制
#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));
}

但是,当我试图编译我的程序时,我会得到以下错误:

代码语言:javascript
复制
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的问题

向尤扎库问好

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-02-03 17:07:55

您的代码中有许多语法错误。下面的示例有效。

注意:下面的 operator-是在T上模板化的,而不是T1T2,因为我不确定您在使用不同类型的向量(例如std::vector<int>std::vector<double> )时是否真的想让operator-工作。

示例代码

代码语言:javascript
复制
#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;
}

示例输出

代码语言:javascript
复制
1 5 

实例化

编辑1

注意:正如@StoryTeller在评论中指出的那样,在just T上模板化operator-将阻止std::vector<int>std::set<int>之间有效使用operator- (如OP所尝试的)。下面的代码使用T1T2来解决这个问题。

示例代码

代码语言:javascript
复制
#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;
}

示例输出

代码语言:javascript
复制
1 5 
1 5 

实例化

票数 4
EN

Stack Overflow用户

发布于 2016-02-03 16:58:06

std::enable_if是一个元库,返回一个类型(默认为无效)。

因此,主operator-语句的格式是错误的。

必须将模板class参数更改为如下所示

代码语言:javascript
复制
class = typename std::enable_if_t<is_STL_container<T1>::value &&
                                  is_STL_container<T2>::value>

或者这个:

代码语言:javascript
复制
class = typename std::enable_if<is_STL_container<T1>::value &&
                                is_STL_container<T2>::value>::type

您可以找到固定程序这里

票数 3
EN

Stack Overflow用户

发布于 2016-02-03 17:04:32

考虑一下这个定义

代码语言:javascript
复制
template <class T1, class T2, class int> int operator- ...

这显然是不正确的,对吧?但您只编写了稍微复杂一些的版本。

你说的是什么

代码语言:javascript
复制
template <class T1, class T2>
typename std::enable_if<whatever>::type
operator- ...
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35182975

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档