区分函数和类 (functor)

distinguish between functions and classes (functor)

提问人:quant 提问时间:8/17/2023 最后编辑:Vlad from Moscowquant 更新时间:8/17/2023 访问量:78

问:

我有一个函数和类,叫做 GreaterThan。

template <typename T>
bool GreaterThan(const T& number)
{
    return number > 100;
}
template <typename T>
class GreaterThan
{
    private:
        T value;
    public:
        GreaterThan(T x) : value(x) {}
        ~GreaterThan() {}
        
        bool operator()(T& compare)
        {
            return compare > value;
        }
};

我怎样才能区分:

  1. std::find_if(v1.begin(), v1.end(),GreaterThan<int>); // error
  2. std::find_if(v1.begin(), v1.end(),GreaterThan<int>(100));

并让编译器知道 1) 应该调用函数?

C++ 函数 模板 functor

评论

5赞 pm100 8/17/2023
@Eljay,那只是说“更改其中一个的名称”
3赞 Pepijn Kramer 8/17/2023
只需给它们起唯一的名字
1赞 quant 8/17/2023
@Jerry Coffinn你是对的!刚刚编辑的问题
1赞 Drew Dormann 8/17/2023
哪个 C++ 编译器允许函数模板和类模板在同一个命名空间中具有相同的名称?
4赞 Jerry Coffin 8/17/2023
@quant:简短的回答是否定的。区分它们是无关紧要的,因为它们一开始就不允许存在。

答:

6赞 Vlad from Moscow 8/17/2023 #1

来自 C++ 20 标准(13 个模板)

7 类模板的名称不得与其他模板相同 模板、类、函数、变量、枚举、枚举器、 命名空间,或在同一作用域 (6.4) 中键入,但 13.7.6. 除了函数模板可以被同名的非模板函数 (9.3.4.6) 或其他 同名函数模板 (13.10.4),模板名称 在命名空间作用域或类作用域中声明应是唯一的,因为 范围。

因此,您的代码无效,因为类模板与函数模板同名。

如果模板在不同的命名空间中声明,则使用限定名称。

这是一个演示程序,

#include <iostream>
#include <vector>
#include <algorithm>

namespace N1
{
    template <typename T>
    bool GreaterThan( const T &number )
    {
        return number > 3;
    }
}

namespace N2
{
    template <typename T>
    class GreaterThan
    {
    private:
        T value;
    public:
        GreaterThan( const T &x ) : value( x ) {}
        ~GreaterThan() {}

        bool operator()( const T &compare ) const
        {
            return compare > value;
        }
    };
}

int main()
{
    std::vector<int> v1 = { 1, 2, 3, 4, 5 };

    auto it1 = std::find_if( v1.begin(), v1.end(), N1::GreaterThan<int> );  
    auto it2 = std::find_if( v1.begin(), v1.end(), N2::GreaterThan<int>( 3 ) );

    if ( it1 != v1.end() ) std::cout << "*it1 = " << *it1 << '\n';
    if ( it2 != v1.end() ) std::cout << "*it2 = " << *it2 << '\n';
}

程序输出为

*it1 = 4
*it2 = 4

如果在同一作用域中使用非模板类和函数,则对于类类型的对象,请使用详细类型说明符。例如

#include <iostream>
#include <vector>
#include <algorithm>

bool GreaterThan( const int &number )
{
    return number > 3;
}

class GreaterThan
{
private:
    int value;
public:
    GreaterThan( const int &x ) : value( x ) {}

    bool operator()( const int  &compare ) const 
    {
        return compare > value;
    }
};

int main()
{
    std::vector<int> v1 = { 1, 2, 3, 4, 5 };

    auto it1 = std::find_if( v1.begin(), v1.end(), GreaterThan );   
    auto it2 = std::find_if( v1.begin(), v1.end(), class GreaterThan( 3 ) );

    if ( it1 != v1.end() ) std::cout << "*it1 = " << *it1 << '\n';
    if ( it2 != v1.end() ) std::cout << "*it2 = " << *it2 << '\n';
}

评论

0赞 Peter 8/17/2023
相关引用并非特定于 C++20 - 迄今为止,每个 C++ 标准中都有相同的措辞(在我写这篇文章时 - 我没有水晶球可以预测标准在未来将如何发展)。唯一的区别是包含部分和段落编号,以及标准之间的交叉引用不同(例如,在C++ 89/90中,引用在第14节“模板”,第5段中)。
0赞 Red.Wave 8/17/2023
ADL 可能提供了一种方法,但这也是糟糕的设计。ADL 实例化表达式可以包装在 lambda 中。