C++推断指向成员模板参数的指针

C++ deduce pointer to member template parameter

本文关键字:参数 指针 成员 C++      更新时间:2023-10-16

我正在尝试使用 C++17 个功能为词典比较编写模板化版本:

#include <type_traits>
#include <set>
#include <vector>
#include <iostream>
namespace compare
{
    template <typename T, auto P, auto ...Ps>
    bool less(const T &t1, const T &t2)
    {
        if constexpr (sizeof...(Ps) == 0)
        {
            return t1.*P < t2.*P;
        }
        else
        {
            if (t1.*P == t2.*P)
            {
                return less<Ps...>(t1, t2);
            }
            else
            {
                return t1.*P < t2.*P;
            }
        }
    }
}
struct my_type
{
    int i = 0;
    std::set<int> s;
};
int main()
{
    my_type t1, t2;
    t2.i = -1;
    std::cout << std::boolalpha << compare::less<my_type, &my_type::i, &my_type::s>(t1, t2) << std::endl;
    return 0;
}

但是,我的示例无法使用最新版本的 GCC 进行编译:

main.cpp: In instantiation of 'bool compare::less(const T&, const T&) [with T = my_type; auto P = &my_type::i; auto ...Ps = {&my_type::s}]':
main.cpp:42:88:   required from here
main.cpp:16:23: error: no matching function for call to 'less<&my_type::s>(const my_type&, const my_type&)'
     return less<Ps...>(t1, t2);
            ~~~~~~~~~~~^~~~~~~~
main.cpp:6:7: note: candidate: template<class T, auto P, auto ...Ps> bool compare::less(const T&, const T&)
  bool less(const T &t1, const T &t2)
       ^~~~
main.cpp:6:7: note:   template argument deduction/substitution failed:

有趣的是,编译器输出没有说明无法推断出哪个模板参数。我知道如何以 C++17 之前的方式实现这一点。我做错了什么?

您在less<Ps...>中缺少T

namespace compare
{
    template <typename T, auto P, auto ...Ps>
    bool less(const T &t1, const T &t2)
    {
        if constexpr (sizeof...(Ps) == 0)
        {
            return t1.*P < t2.*P;
        }
        else
        {
            if (t1.*P == t2.*P)
            {
                return less<T, Ps...>(t1, t2);
            }
            else
            {
                return t1.*P < t2.*P;
            }
        }
    }
}

现场观看

旁白:为了适应标准库定义概念 Compare 的方式,我建议删除 == 的使用,而是使用

if (return t1.*P < t2.*P)
{
    return true;
}
if (return t2.*P < t1.*P)
{
    return false;
}
return less<T, Ps...>(t1, t2);