本文介绍了无法定义从属typedef的成员的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写自定义延迟字符串类。

 模板< typename charT,typename traits = std :: char_traits< charT> ;> 
class lazy_basic_string
{
class char_proxy
{
char_proxy& operator =(charT ch);
};

char_proxy operator [](size_type i);
}

然后我想在类声明之外定义这些方法。

 模板< typename charT,typename traits> 
using char_proxy = typename lazy_basic_string< charT,traits> :: char_proxy;

template< typename charT,typename traits>
char_proxy< charT,traits>& char_proxy< charT,traits> :: operator =(charT ch)
{
...
}

但我遇到了编译错误:

所以我不知道这里有什么问题。
为什么编译器不能使用快捷方式char_proxy而不是lazy_basic_string :: char_proxy?

解决方案

应由该标准明确规定。我最近似乎得到的是 [temp.class]

这意味着,到类模板的名称,而不是通过别名模板。



应该很容易看到为什么这是必要的;作为别名模板可以导致任意复杂的计算,为了将类模板成员的使用与潜在定义相匹配,编译器必须对别名模板参数的每个可能组合执行该计算:

 模板< class T> struct S {void f(); }; 
template< class T>使用s_t = std :: conditional_t< sizeof(T)%8 == 0,
S< T>,S< T *>
template< class T> void s_t< T> :: f(){}

int main(){S< int> s; s.f(); } // defined?有趣的是,clang(3.7)允许在类模板成员定义中使用别名模板,但是可以使用别名模板。只有在它是一个直接的身份计算:

  template< class> struct T {void f(); }; 
template< class C>使用id_t = C;
template< class C>使用t_t = T< id_t C> ;;
template< class C> void t_t< C> :: f(){} // OK?


I am writing custom lazy string class.

template <typename charT, typename traits = std::char_traits<charT>>
class lazy_basic_string
{
    class char_proxy
    {
        char_proxy& operator=(charT ch);
    };

    char_proxy operator[](size_type i);
}

Then i want to define these methods outside of class declaration.

template <typename charT, typename traits>
using char_proxy = typename lazy_basic_string<charT, traits>::char_proxy;

template <typename charT, typename traits>
char_proxy<charT, traits>& char_proxy<charT, traits>::operator=(charT ch)
{
    ...
}

But i got compile error:

So i can't figure out what's problem here.Why compiler can't use shortcut char_proxy instead of lazy_basic_string::char_proxy ?

解决方案

This doesn't seem to be particularly well-specified by the Standard. The closest I can appear to get is [temp.class]:

This implies, though does not exactly state, that an out-of-line class template member definition should refer to the class template by its name, and not via an alias template.

It should be reasonably easy to see why this is necessary; as an alias template can result in an arbitrarily complex computation, in order to match a use of a class template member against a potential definition the compiler would have to perform that computation on every possible combination of alias template parameters:

template<class T> struct S { void f(); };
template<class T> using s_t = std::conditional_t<sizeof(T) % 8 == 0,
    S<T>, S<T*>>;
template<class T> void s_t<T>::f() {}

int main() { S<int> s; s.f(); }    // defined?

Interestingly, clang (3.7) allows the use of an alias template in a class template member definition, but only where it is a straight identity calculation:

template<class> struct T { void f(); };
template<class C> using id_t = C;
template<class C> using t_t = T<id_t<C>>;
template<class C> void t_t<C>::f() {}    // OK??

这篇关于无法定义从属typedef的成员的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-04 02:25
查看更多