5

我正在尝试在模板结构中使用一些 SFINAE。我将我的问题减少到以下,并且可以使这项工作:

template<bool mybool>
struct test {
    void myfunc();
};

template<bool mybool>
void test<mybool>::myfunc() {
    std::cout << "test true" << std::endl;
}
template<>
void test<false>::myfunc() {
    std::cout << "test false" << std::endl;
}

int main(int argc, char ** argv) {
    test<true> foo;
    test<false> bar;
    foo.myfunc();
    bar.myfunc();
}

使用此代码,我得到结果:

test true
test false

但是,如果我想考虑我struct test的模板参数不止一个,我尝试像这样调整上面的内容:

template<int myint, bool mybool>
struct test {
    void myfunc();
};

template<int myint, bool mybool>
void test<myint,mybool>::myfunc() {
    std::cout << "test true" << std::endl;
}
template<int myint>
void test<myint,false>::myfunc() { 
//error: invalid use of incomplete type 'struct test<myint, false>'
    std::cout << "test false" << std::endl;
}

int main(int argc, char ** argv) {
    test<1,true> foo;
    test<1,false> bar;
    foo.myfunc();
    bar.myfunc();
}

我对不完整类型“结构测试”的使用无效。

我走错方向了吗?有没有办法做我想做的事?谢谢你的帮助!

4

4 回答 4

6

你不能部分专门化成员函数,你应该partially specialize完整的结构。以下示例将正常工作

template<int myint, bool mybool>
struct test {
    void my_func();
};

template<int myint, bool mybool>
void test<myint,mybool>::my_func() {
    std::cout << "test true" << std::endl;
}

template<int myint>
struct test<myint, false> {
   void my_func();
};

template<int myint>
void test<myint,false>::my_func() { 
//error: invalid use of incomplete type 'struct test<myint, false>'
    std::cout << "test false" << std::endl;
}

int main(int argc, char ** argv) {
    test<1,true> foo;
    test<1,false> bar;
    foo.my_func();
    bar.my_func();
}
于 2013-05-24T08:56:23.063 回答
3

If you want to avoid redefining your class, which you would have to do since partial specialisation of (member) functions is not allowed, you could decompose your type. This will minimise the repetition of code:

template<int myint, bool mybool>
struct test {
    char some_var;
    std::vector<int> more_var;
    void my_func();
};

Change to:

template<int myint>
struct test_static {
  protected:
    char some_var;
    std::vector<int> more_var;
};

template <int myint, bool mybool>
struct test : private test_static<myint> {
    void my_func() {
      // default case
    }
};
template <int myint>
struct test<myint,false> : private test_static<myint> {
    void my_func() {
      // special case
    }
};

Of course, if you want full visibility of all members to the outside, don't make them protected in the first place and use public instead of private inheritance.

于 2013-05-24T09:12:11.553 回答
3

首先看一下关于 SFINAE 原则的这个问题以刷新我的记忆,我试图以最小的代码冗余来获得您正在寻找的结果。

我还检查了有关该主题的维基百科文章,这表明您也需要类似的功能boost::enable_if来有条件地选择您的功能实现:

// simplified version of boost::enable_if_c and disable_if_c to match your exact need

template <bool B>
struct enable_if_c {
    typedef void type;
};

struct enable_if_c<false>{};

template <bool B>
struct disable_if_c {
    typename void type;
};

struct disable_if_c<true> {};

template<bool mybool, typename T>
struct test {
    template <bool d> 
    typename enable_if_c<d>::type my_func_impl(){
        cout << "true" << endl;
    }
    template <bool d>
    typename disable_if_c<d>::type my_func_impl(){
         cout << "false" << endl;
    }
    void my_func(){ my_func_impl<mybool>(); }
};

您可以my_func_impl使用以下语法定义结构外部的主体:

 template <bool mybool, typename T>
 template <bool d>
 typename enable_if_c<d>::type test<mybool,T>::my_func_impl(){
     cout << "true" << endl;
 }

问题的棘手之处在于您不能依赖简单的重载,因为您想要相同的函数原型,因此需要专门定义一个或另一个实现。

于 2013-05-24T11:33:43.840 回答
0

您可以对diderc提供的答案进行一些改进,只需稍作修改,即可避免使用会污染函数名称的辅助函数:

代替 :

template <bool d> 
typename enable_if_c<d>::type my_func_impl(){
    cout << "true" << endl;
}
template <bool d>
typename disable_if_c<d>::type my_func_impl(){
     cout << "false" << endl;
}
void my_func(){ my_func_impl<mybool>(); }

写吧 :

template <bool d = mybool> 
typename enable_if_c<d>::type my_func(){
    cout << "true" << endl;
}
template <bool d = mybool>
typename disable_if_c<d>::type my_func(){
     cout << "false" << endl;
}

如果您可以使用 C++11,那么您可以将 enable_if_c 和 disable_if_c 替换为std::enable_if

(我无法评论他的答案,所以我发布了我自己的)

于 2013-05-24T22:03:31.057 回答