首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >clang -如何在头文件中声明静态const?

clang -如何在头文件中声明静态const?
EN

Stack Overflow用户
提问于 2017-11-02 06:56:02
回答 1查看 649关注 0票数 3

给定头文件中的以下模板,以及几个专门化:

代码语言:javascript
复制
template<typename> class A {
        static const int value;
};

template<> const int A<int>::value = 1;
template<> const int A<long>::value = 2;

使用clang-5构建时,它会导致包含文件的每个源单元出现错误,所有这些都抱怨A<int>::valueA<long>::value的多个定义。

起初,我认为模板的专门化可能需要放在特定的翻译单元中,但是在检查规范时,显然应该允许这样做,因为这个值是一个常量整数。

我是不是做错什么了?

编辑:如果我将定义移动到单个翻译单元,那么我就不能再在一个A<T>::value上下文中使用const int的值(例如,它的值用于计算另一个const赋值的值),所以这个值确实需要在一个标头中。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-11-02 09:26:15

在c++11中,你也许可以走那条路:

代码语言:javascript
复制
template<typename> class B {
    public:
        static const int value = 1;
};

template<> class B<long> {
    public:
        static const int value = 2;
};

template<typename T> const int B<T>::value;

如果您只想专门化值var,则可以为此使用CRTP。

通过C++17,您可以将您的定义内联:

代码语言:javascript
复制
template<> inline const int A<int>::value = 1;
template<> inline const int A<long>::value = 2;

另外,您还可以从c++17中删除constexpr::value;的“template constexpr::value”:

代码语言:javascript
复制
template<typename> class C {
    public:
        static constexpr int value = 1;
};

template<> class C<long> {
    public:
        static constexpr int value = 2;
};

// no need anymore for: template<typename T> const int C<T>::value;

c++11的另一种解决方案可以是使用内联方法,而不是c++17允许的内联vars:

代码语言:javascript
复制
template<typename T> class D { 
    public:
        static constexpr int GetVal() { return 0; }

        static const int value = GetVal();
};  

template <> inline constexpr int D<int>::GetVal() { return 1; }
template <> inline constexpr int D<long>::GetVal() { return 2; }

template< typename T>
const int D<T>::value;

除了最后一次编辑之外:

要同时在其他相关定义中使用您的值,如果您使用内联constexpr方法,它似乎是最易读的版本。

编辑: clang的“特殊”版本,因为正如OP告诉我们的那样,clang抱怨“在实例化之后发生了专门化”。我不知道克朗和gcc在那个地方是不是错了.

代码语言:javascript
复制
template<typename T> class D {
    public:
        static constexpr int GetVal();
        static const int value;
};


template <> inline constexpr int D<int>::GetVal() { return 1; }
template <> inline constexpr int D<long>::GetVal() { return 2; }

template <typename T> const int D<T>::value = D<T>::GetVal();

int main()
{
    std::cout << D<int>::value << std::endl;
    std::cout << D<long>::value << std::endl;
}

我已经告诉过,如果不需要重新定义完整的类,那么CRTP是可能的。我检查了clang上的代码,它编译时没有任何警告或错误,因为OP注释说他不知道如何使用它:

代码语言:javascript
复制
template<typename> class E_Impl {
    public:
        static const int value = 1;
};

template<> class E_Impl<long> {
    public:
        static const int value = 2;
};

template<typename T> const int E_Impl<T>::value;

template < typename T>
class E : public E_Impl<T>
{
    // rest of class definition goes here and must not specialized
    // and the values can be used here!

    public:

        void Check()
        {
            std::cout << this->value << std::endl;
        }
};


int main()
{
    E<long>().Check();
    std::cout << E<long>::value << std::endl;
    E<int>().Check();
    std::cout << E<int>::value << std::endl;
}
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47069305

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档