Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/140.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何重写它以使其符合C++;标准_C++_Templates_Template Specialization - Fatal编程技术网

C++ 如何重写它以使其符合C++;标准

C++ 如何重写它以使其符合C++;标准,c++,templates,template-specialization,C++,Templates,Template Specialization,下面的代码片段演示了我想要实现的目标,即创建两个模板专门化(这里是主模板和专门化),一个用于非常量成员函数,另一个用于常量成员函数: // instantiate for non-const member functions template <typename C, void(C::*F)()> struct A {}; // instantiate for const member functions template <typename C, void(C::*F)()

下面的代码片段演示了我想要实现的目标,即创建两个模板专门化(这里是主模板和专门化),一个用于非常量成员函数,另一个用于常量成员函数:

// instantiate for non-const member functions
template <typename C, void(C::*F)()>
struct A {};

// instantiate for const member functions
template <typename C, void(C::*F)() const>
struct A<C const, F> {};

struct foo
{
    void bar() const {}
    typedef A<foo const, &foo::bar> bar_type;

    void baz() {}
    typedef A<foo, &foo::baz> baz_type;
};
//为非常量成员函数实例化
模板
结构A{};
//实例化常量成员函数
模板
结构A{};
结构foo
{
void bar()常量{}
类型定义为条形图类型;
void baz(){}
类型定义为baz_类型;
};
虽然此代码使用GCC4.7、Intel 13.0和MSVC 2012可以很好地编译,但使用Clang 3.3或Comeau 4.3.10.1编译失败。我相信Clang是对的

如何重写此代码以使其符合标准(即使用Clang编译)

以下是编译错误:

test_6.cpp:22:26: error: non-type template argument of type 'void (foo::*)() const' cannot be converted to a value of type 'void (const foo::*)()'
    typedef A<foo const, &foo::bar> bar_type;
                         ^~~~~~~~~
test_6.cpp:7:33: note: template parameter is declared here
template <typename C, void (C::*F)()>
                                ^
test_6.cpp:22:26:错误:类型为'void(foo::*)()const'的非类型模板参数无法转换为类型为'void(const foo:*)()的值
类型定义为条形图类型;
^~~~~~~~~
test_6.cpp:7:33:注意:此处声明了模板参数
模板
^
这不是(部分)专门化的工作方式。在专门化中提供参数时,它必须与相应参数的种类相匹配

主模板有一个指向-非常量成员函数(PTNCMF)参数的指针,该参数应为此类模板参数。但是,您的部分专门化将指向-const-member函数(PTCMF)的指针作为参数传递,从而造成不匹配。PTCMF不能转换为PTNCMF,因此部分专用化无效

问题到此为止,我们开始解决问题。您需要将参数的类型与实际参数分开。一种方法是,简单地断言
const
类类型仅与PTCMF匹配

#include <type_traits>

template<class Fty>
struct is_ptcmf : std::false_type{};

template<class C, class R, class... Args>
struct is_ptcmf<R (C::*)(Args...) const> : std::true_type{};

template<class C, class Fty, Fty F>
struct A{
  static_assert(std::is_const<C>() == is_ptcmf<Fty>(), "Must pair const with const.");
};
#包括
模板
结构是_ptcmf:std::false_type{};
模板
结构是_ptcmf:std::true_type{};
模板
结构A{
静态_断言(std::is_const()==is_ptcmf(),“必须将const与const配对”);
};


然后使用将是
A
。如果您认为存在一些冗余,我同意,但是。

如果您将成员函数类型设置为模板参数,则可以为不同的成员函数类型专门化模板:

template <typename C, typename F, F>
struct A;  // undefined

template <typename C, void(C::*f)()>
struct A<C, void(C::*)(), f> {};

template <typename C, void(C::*f)() const>
struct A<C const, void(C::*)() const, f> {};

struct foo
{
    void bar() const {}
    typedef A<foo const, decltype(&foo::bar), &foo::bar> bar_type;

    void baz() {}
    typedef A<foo, decltype(&foo::baz), &foo::baz> baz_type;
};
模板
结构A;//未定义
模板
结构A{};
模板
结构A{};
结构foo
{
void bar()常量{}
类型定义为条形图类型;
void baz(){}
类型定义为baz_类型;
};

仅就记录而言,以下是我解决问题的方法:

template <typename F, F ptr>
struct A;  // undefined

template <typename C, void (C::*F)()>
struct A<void (C::*)(), F> {};

template <typename C, void (C::*F)() const>
struct A<void (C::*)() const, F> {};

struct foo
{
    void bar() const {}
    typedef A<decltype(&foo::bar), &foo::bar> bar_type;

    void baz() {}
    typedef A<decltype(&foo::baz), &foo::baz> baz_type;
};
模板
结构A;//未定义
模板
结构A{};
模板
结构A{};
结构foo
{
void bar()常量{}
类型定义为条形图类型;
void baz(){}
类型定义为baz_类型;
};

谢谢大家的见解

为什么不向我们展示编译错误呢?为什么不提供版本信息?“它无法编译”…并显示错误消息?我添加了编译器版本和错误消息。您的部分专门化与主模板不匹配,因此不是有效的专门化。部分专门化的第二个参数与主模板的第二个参数的类型不同。我想知道如何重写它:-p这并不能回答我的问题。我已经说过Clang是对的,这个代码是不一致的。@StephenLin:到目前为止,看起来他只是想确保两个都是成对的,但是,如果这不是他想要的,使用一点
enable\u if
magic,很容易创建专门化场景。@Xeo我删除了注释,因为我认为我误读了您的代码,但在误读之后,我显然意识到我没有。不管怎样,是的,这没什么大不了的,只是想指出,看起来他想要两个不同的专业;当然,使用SFINAE应该很容易做到。目前专门化根本没有考虑原始函数类型。