简化模板接口,删除冗余类型

发布于 2025-02-04 21:43:48 字数 1939 浏览 1 评论 0原文

#include <cstddef>
#include <utility>

template <size_t N, typename... V>
struct T {
    int test(size_t n, const char** ss) {
        if (N > n)
            return 1;
        return []<size_t... I>(const char* ss[N], std::index_sequence<I...>) {
            return test_impl(ss[I]...);
        }(ss, std::make_index_sequence<N>{});
    }

    // Ideally this would be templated, solving my problem:
    // i.e. move "typename... V" from the struct to this function.
    virtual int test_impl(V...) = 0;
};

template <typename U, size_t N, typename... V>
struct T1 : T<N, V...> {
    U value;
    int (*tester)(U*, V...);

    int test_impl(V... v) {
        return tester(&value, v...);
    }

    // virtual is not an aggregate
    T1(U value, int (*tester)(U*, V...))
        : value{value}, tester{tester}
        {};
};

int test1(int* v, const char* s1, const char* s2) {
    return 1;
}

template <typename... V>
int test2(int* v, V... ss) {
    return 1;
}

C ++非常擅长从函数参数推导模板功能参数,但是不允许虚拟函数模板。我被迫将函数模板参数移至结构模板,并发现C ++不擅长从成员变量推导模板结构参数。最后,我被迫将冗余信息指定为模板,该信息使t1/t接口难以使用?我该如何解决?

例如,在这里我们知道:

  • sizeof ...(v)== n
  • exttype(v)必须是const char*
  • template参数u可以仅从t1构造
  • 函数模板参数v ...的参数中得出。 > t1 构造器
  • 遵循该模板参数n可以仅从t1构造函数的参数中得出。
int main() {
    // The '2' and the 'const char*'... are redundant
    T1 a = T1<int, 2, const char*, const char*>(10, test1);
    T1 b = T1<int, 2, const char*, const char*>(10, test2);

    // There is enough information here to deduce the values
    T1 c = T1(10, test1);

    // There is enough information here to deduce the values
    T1 d = T1<..., 2, ...>(10, test2);
}
#include <cstddef>
#include <utility>

template <size_t N, typename... V>
struct T {
    int test(size_t n, const char** ss) {
        if (N > n)
            return 1;
        return []<size_t... I>(const char* ss[N], std::index_sequence<I...>) {
            return test_impl(ss[I]...);
        }(ss, std::make_index_sequence<N>{});
    }

    // Ideally this would be templated, solving my problem:
    // i.e. move "typename... V" from the struct to this function.
    virtual int test_impl(V...) = 0;
};

template <typename U, size_t N, typename... V>
struct T1 : T<N, V...> {
    U value;
    int (*tester)(U*, V...);

    int test_impl(V... v) {
        return tester(&value, v...);
    }

    // virtual is not an aggregate
    T1(U value, int (*tester)(U*, V...))
        : value{value}, tester{tester}
        {};
};

int test1(int* v, const char* s1, const char* s2) {
    return 1;
}

template <typename... V>
int test2(int* v, V... ss) {
    return 1;
}

C++ is very good at deducing template function parameters from function arguments, but virtual function templates are not allowed. I am forced to move the function template parameters to the struct template, and find that C++ is not good at deducing template struct parameters from member variables. In the end I am forced to specify redundant information to the template which makes the T1/T interface difficult to use? How can I fix this?

For example, here we know that:

  • sizeof...(V) == N
  • decltype(V) must be const char*
  • template parameter U can be deduced solely from the argument of the T1 constructor
  • template parameter V... can be deduced solely from the argument of the T1 constructor
  • from which it follows that template parameter N can be deduced solely from the argument of the T1 constructor.
int main() {
    // The '2' and the 'const char*'... are redundant
    T1 a = T1<int, 2, const char*, const char*>(10, test1);
    T1 b = T1<int, 2, const char*, const char*>(10, test2);

    // There is enough information here to deduce the values
    T1 c = T1(10, test1);

    // There is enough information here to deduce the values
    T1 d = T1<..., 2, ...>(10, test2);
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

纵山崖 2025-02-11 21:43:48

sizeof ...(v)== n

no,编译器不知道。 (查看错误消息),

由于您有此先决条件,因此您不必拥有模板参数n

template <typename... V>
struct T {
    
    int test(size_t n, const char** ss) {
        constexpr int N = sizeof...(V);
        if (N > n)
            return 1;
        return []<size_t... I>(const char* ss[N], std::index_sequence<I...>) {
            return test_impl(ss[I]...);
        }(ss, std::make_index_sequence<N>{});
    }

    // Ideally this would be templated, solving my problem:
    // i.e. move "typename... V" from the struct to this function.
    virtual int test_impl(V...) = 0;
};

参见在线演示

sizeof...(V) == N

No, the compiler doesn't know it. (Take a look at the error messages)

Since you have this prequisite, you don't have to have the template parameter N.

template <typename... V>
struct T {
    
    int test(size_t n, const char** ss) {
        constexpr int N = sizeof...(V);
        if (N > n)
            return 1;
        return []<size_t... I>(const char* ss[N], std::index_sequence<I...>) {
            return test_impl(ss[I]...);
        }(ss, std::make_index_sequence<N>{});
    }

    // Ideally this would be templated, solving my problem:
    // i.e. move "typename... V" from the struct to this function.
    virtual int test_impl(V...) = 0;
};

See online demo

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文