可变参数模板和函数的指针:哪种编译器正确?

天顶

我找不到更好的标题,但是如果您有正确的想法,请随时进行修改。实际上,它比GCC和clang都要好


我试图找出这段代码有什么问题:

template <typename... T>
struct S;

template <typename T, typename... U>
struct S<T, U...>: S<U...> {
    using S<U...>::f;

    template<void(*F)(const T &)>
    void f() { }
};

template<>
struct S<> {
    void f();
};

template<typename... T>
struct R: S<T...> {
    using S<T...>::f;

    template<typename U, void(*F)(const U &)>
    void g() {
        this->template f<F>();
    }
};

void h(const double &) { }

int main() {
    R<int, double> r;
    r.g<double, h>();
}

它可以使用GCC 4.9编译(请参阅此处),但不能使用clang 3.8.0进行编译(请参阅此处)。

哪个编译器正确,为什么?
而且,我该怎么做才能看到两个编译器都在编译代码?

巴里

我相信clang在这里是正确的,这是一个gcc错误。首先,让我们从一个简化的示例开始:

struct U {
    template<int > void foo() { }
};

struct X : U {
    using U::foo;
    template<void* > void foo() { }
};

int main() {
    X{}.foo<1>(); // gcc ok, clang error
}

来自[namespace.udecl]

using-declaration将基类中的声明带到派生类中时,派生类中的成员函数和成员函数模板将覆盖和/或隐藏具有相同名称,parameter-type-list的成员函数和成员函数模板(8.3。 5),cv限定符和ref限定符(如果有)在基类中(而不是冲突)。此类隐藏或覆盖的声明从using-declaration引入的声明集中排除

U::fooX::foo具有相同的名称,parameter-type-list(无),cv限定(无)和ref限定符(无)。因此,X::foo 隐藏 U::foo而不是重载它,我们肯定会将错误的类型传递给X::foo

只需在不同的函数指针类型上重载(而不是将它们用作模板参数)即可:

template <typename T, typename... U>
struct S<T, U...> : S<U...> {
    using S<U...>::f;

    void f(void (*F)(const T&)) { }
};

或者,如果您确实需要将函数指针作为模板参数,则仍可以通过将其包装为标记类型来重载:

template <class T>
using fptr = void(*)(const T&);

template <class T, fptr<T> F>
using func_constant = std::integral_constant<fptr<T>, F>;

并通过以下方式传播:

template <typename T, typename... U>
struct S<T, U...>: S<U...> {
    using S<U...>::f;

    template <fptr<T> F>
    void f(func_constant<T, F> ) { }
};

和:

template <class U, fptr<U> F>
void g() {
    this->f(func_constant<U, F>{});
}

parameter-type-list的定义未提及模板参数。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

静态const成员变量,可变参数模板和&&的编译器错误或正确行为

编译器跳过C ++中的可变参数模板/函数

隐藏成员函数模板-哪个编译器正确?

编译器无法推断可变参数模板的模板参数

为什么Clang ++编译器无法编译以下可变参数模板代码?

具有可变参数模板的模板元编程:编译器错误

可变参数类模板和继承-默认编译器生成的构造函数

是编译器还是我自己:从包含lambda的可变参数模板继承

函数指针参数的可变参数模板参数推导

以成员函数指针为参数的可变参数模板

具有可变参数模板参数的函数指针

可变参数模板函数确定函数指针的返回类型

可变参数函数和可变参数模板重载查找

使用可变参数模板(gcc,clang)的成员函数指针包装器

用可变参数模板在C ++中包装函数指针

具有可变参数模板的成员函数指针

g ++和clang ++的行为不同,指向可变参数模板函数的指针

GCC因可变参数模板和指向成员函数的指针而失败

使用可变参数模板和函数指针的简单EventHandler / Provider

编译器如何确定要调用的函数模板?

C ++ gcc函数模板重载编译器问题

内部编译器错误:gcc中的分段错误。发送可变参数模板到结构时

如何正确使用可变参数模板函数

演绎指南,模板和子对象:哪种编译器正确?

可变参数模板函数参数和引用类型推导

C ++将模板参数包从一个可变参数模板传递到另一个可变参数模板会导致编译器错误

C ++:可变参数模板和函数重载

命名空间和类中的可变参数模板函数

可变参数函数模板接受任何指针(指向变量,函数,成员函数等)作为参数