简体   繁体   English

在clang vs gcc和msvc中按方法指针的模板

[英]Template by method pointer in clang vs gcc and msvc

I have this function: 我有这个功能:

template <typename T, void (T::*pf)()>
void call(T& t)
{
    (t.*pf)();
}

If I have class foo with a method with the appropriate signature (say bar ) I can call it like this call<foo, &foo::bar>(); 如果我有一个带有相应签名的方法的类foo (比如bar ),我可以像call<foo, &foo::bar>();那样调用它call<foo, &foo::bar>(); and it's fine. 这没关系。 However if bar is const gcc and msvc are happy to compile it when called like this call<const foo, &foo::bar>() . 但是,如果barconst gcc,msvc很乐意在调用时调用它,就像call<const foo, &foo::bar>() Clang complains that the second template parameter is invalid. Clang抱怨第二个模板参数无效。 When I put const in the template arguments ( void (T::*pf)() const ) all tree compile it. 当我将const放入模板参数( void (T::*pf)() const )时,所有树都编译它。

Now, this is not a huge issue, but my code becomes much much cleaner if I don't have to write this wretched const in the template arguments. 现在,这不是一个大问题,但如果我不必在模板参数中编写这个可怜的const ,我的代码会变得更加清晰。

So the question basically is: What does the standard say about this? 所以问题基本上是:标准对此有何看法? Is this a clang bug or are gcc and msvc just letting it slide because they're cool like that? 这是一个铿锵的bug还是gcc和msvc只是让它滑动因为它们很酷?

PS Here's a link to a complete repro program: http://codepad.org/wDBdGvSN PS这是一个完整的repro程序的链接: http//codepad.org/wDBdGvSN

The const -ness of a method is part of the 'signature' of it. 方法的const是它的“签名”的一部分。 So, the proper way to define and use a pointer to member is: 因此,定义和使用指向成员的指针的正确方法是:

R (Obj::*)(Args)       // for non-const member
R (Obj::*)(Args) const // for const member

Note that a const member can be called on a non-const object, which is not the case with R (const Obj::*)(Args) . 请注意,可以在非const对象上调用const成员,而R (const Obj::*)(Args)则不是这种情况。

A way to solve this is to abstract such function pointers, by defining 'call wrappers': 解决这个问题的方法是通过定义'call wrappers'来抽象这样的函数指针:

template<typename O, void (O::* f)()>
struct NonConstFunc
{
    static void call(O* o)
    {
        (o->*f)();
    }
};

template<typename O, void (O::* f)() const>
struct ConstFunc
{
    static void call(O* o)
    {
        (o->*f)();
    }
};

Then, you can use it the following way (here the abstraction takes place): 然后,您可以通过以下方式使用它(这里是抽象):

template<typename Obj, typename Function>
void call(Obj* o)
{
    Function::call(o);
}

There is a live example here . 这里有一个现实的例子

This is just the main idea. 这只是主要想法。 You can extend it with automatic detection of whether the method is const or not, without changing the user code. 您可以通过自动检测方法是否为const来扩展它,而无需更改用户代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Consexpr function 对模板参数 object 的评估(MSVC 与 clang/gcc) - Constexpr function evaluation on a template parameter object (MSVC vs clang/gcc) Constexpr函数指针作为模板参数MSVC vs GCC - Constexpr function pointer as template argument MSVC vs GCC Clang vs GCC vs MSVC模板转换运算符 - 哪个编译器是对的? - Clang vs GCC vs MSVC template conversion operator - which compiler is right? 引用这个指针:GCC vs clang - Reference to the this pointer: GCC vs clang GCC &amp; Clang vs MSVC Bug,同时在函数模板的相同参数子句中扩展模板参数包 - GCC & Clang vs MSVC Bug while expanding template parameter pack in the same parameter clause for function templates GCC vs Clang & MSVC 使用非类型模板参数时出现错误 - GCC vs Clang & MSVC Bug while using non type template parameter Clang vs MSVC:模板函数原型的处理 - Clang vs MSVC: Treatment of template function prototypes 命名空间 scope - gcc 与 clang 与 msvc 中的外部 - extern in namespace scope - gcc vs clang vs msvc const 指针专业化使用 MSVC 生成未解析的符号,并且适用于 GCC/Clang - const pointer specialization produces unresolved symbol with MSVC and is fine with GCC/Clang 原子 function 指针调用在 gcc 中编译,但在 clang 和 msvc 中不编译 - Atomic function pointer call compiles in gcc, but not in clang and msvc
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM