Define friend function template of class template

好久不见. 提交于 2019-12-10 16:32:00

问题


I want to define a function template of a class template. The code looks like this.

template<int M>
struct test{
private:
    int value;

    template<int N = 2 * M>
    friend auto foo(test const t){
        test<N> r;
        r.value = t.value;
        return r;
    }
};

int main(){
    test<1> t;
    foo(t);// expected to return test<2>
    foo<1>(t);// expected to return test<1>
    foo<3>(t);// expected to return test<3>
}

But it won't compile. Compared with previous problems, the following lists the differences.

  1. The result of the function template involves another instatiation of the class template. It seems that the function template has to be defined outside. But I am not sure.
  2. The function template uses default template arguments. So, if the function template is defined outside the class, a helper function template is required.

Compiling Errors with g++ -std=c++1z:

a.cpp: In instantiation of 'auto foo(test<M>) [with int N = 2; int M = 1]':
a.cpp:16:10:   required from here
a.cpp:4:9: error: 'int test<2>::value' is private
     int value;
         ^
a.cpp:9:17: error: within this context
         r.value = t.value;
                 ^
a.cpp: In instantiation of 'auto foo(test<M>) [with int N = 3; int M = 1]':
a.cpp:18:13:   required from here
a.cpp:4:9: error: 'int test<3>::value' is private
     int value;
         ^
a.cpp:9:17: error: within this context
         r.value = t.value;
                 ^

A possible workaround, yet not correct either.

template<int M>
struct test{
private:
    int value;

    template<int NA, int NR>
    friend test<NR> foo_impl(test<NA> const&);
};

template<int NA, int NR>
test<NR> foo_impl(test<NA> const& t){
    test<NR> r;
    r.value = t.value;
    return r;
}

template<int NR, int NA>
auto foo(test<NA> const& t){
    return foo_impl<NA, NR>;
}

template<int NA>
auto foo(test<NA> const& t){
    return foo_impl<NA, NA * 2>(t);
}

int main(){
    test<1> t;
    foo(t);
    foo<3>(t);
    foo<1>(t);
}

Error:

t.cpp: In function 'int main()':
t.cpp:31:13: error: call of overloaded 'foo(test<1>&)' is ambiguous
     foo<1>(t);
             ^
t.cpp:18:6: note: candidate: auto foo(const test<NR>&) [with int NR = 1; int NA = 1]
 auto foo(test<NA> const& t){
      ^
t.cpp:23:6: note: candidate: auto foo(const test<NA>&) [with int NA = 1]
 auto foo(test<NA> const& t){
      ^

回答1:


After your edit, one possible way (which may not be better than your workaround - but work for all call) would be to use a default value for the parameter N:

template<int M>
struct test{
private:
    int value;

    template<int K, int U, int P>
    friend test<P> foo(test<U> const t);

};

template <int N = 0, int M, int P = ((N == 0) ? M * 2 : N)>
test<P> foo (test<M> const t) {
  test<P> r;
  r.value = t.value;
  return r;
}

int main(){
    test<1> t;
    test<2> p1 = foo(t);
    test<3> p2 = foo<3>(t);
    test<1> p3 = foo<1>(t);
}

This may not be prettier than your version...


The problem here is that you are declaring foo<N> a friend of test<M> while you want it to be a friend of any test<...>. You should do the following:

template<int M>
struct test{
private:
    int value;

    template<int U, int K>
    friend test<K> foo(test<U> const t);
};

template <int M, int N = 2 * M>
test<N> foo (test<M> const t) {
    test<N> r;
    r.value = t.value;
    return r;
}

int main(){
    test<1> t;
    foo(t);
}

Here you are saying:

Any function test<K> foo<U, K> (test<U> const) is a friend of any test<...>.



来源:https://stackoverflow.com/questions/37882049/define-friend-function-template-of-class-template

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!