仅针对带有枚举非类型模板参数的C ++模板函数的专业化 [英] Specializations only for C++ template function with enum non-type template parameter

查看:121
本文介绍了仅针对带有枚举非类型模板参数的C ++模板函数的专业化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此问题与该问题有关,只是与处理类型名称模板有关参数,我正在尝试使用枚举非类型模板参数。

This question is related to this one except that rather than dealing with typename template parameters, I am trying to use an enum non-type template parameter.

是否有可能只有专门化的模板化(类成员函数),而没有一般性(工作) )(对于非类型模板参数的定义)?

Is it possible to have a templated (class member function) with only specializations, no general (working) definition in the case of non-type template parameter?


  1. 我可以通过在类主体并仅提供专业知识,但是使用未定义的模板参数进行的任何误用调用在链接之前不会产生错误。更糟糕的是,缺少的符号隐式地指代枚举的整数值而不是其名称,因此它会使其他开发人员感到困惑。

  1. I was able to get one version working, by declaration in the class body and providing specializations only, but any misuse calling with a non-defined template parameter doesn't produce an error until linking. What's worse is the missing symbol cryptically refers to the enum's integral value and not its name, so it would be confusing to other developers.

我能够得到引用的问题中的 BOOST_STATIC_ASSERT 技术仅适用于类型名模板参数。

I was able to get the BOOST_STATIC_ASSERT technique from the referenced question to work for typename template parameter only.

此代码演示了这个想法。我不希望编译 CAT 版本的电话:

This code demonstrates the idea. I don't want the CAT-version call to compile:

#include <iostream>
#include <boost/static_assert.hpp>

// CLASS HEADER FILE:
struct foo_class
{
    enum AllowedTypes { DOG, CAT };

    template <AllowedTypes type>
    void add_one_third( double bar ) const
    {
        BOOST_STATIC_ASSERT_MSG(sizeof(type)==0, "enum type not supported.");
    }
};

// CLASS SOURCE FILE
template<>
void foo_class::add_one_third<foo_class::DOG>( double bar ) const
{
    std::cout << "DOG specialization: " << bar + 1./3. << std::endl;
}


// USER SOURCE FILE
int main()
{
    std::cout << "Template Specialization!\n\n";

    foo_class a;
    a.add_one_third<foo_class::DOG>(3.0); // should succeed
    // Compilation fails with or without the following line:
    a.add_one_third<foo_class::CAT>(3.0); // should fail at compile-time

    return 0;
}

背景
我有一个带有枚举 ArgType和名称的类成员函数。

Background: I have a class member function that takes an enum "ArgType" and a name.

void declareKernelArgument( ArgType type, std::string name );

该定义已变成 if..else..if .. else 列表,用于六个左右的ArgType案例。我还必须有最后一个案例,该案例会为不允许的ArgType引发异常。我认为将ArgType移到模板参数并为每个允许的ArgType提供专门化会更干净。

The definition has turned into an if..else..if..else list for the half-dozen or so allowed ArgType cases. I also have to have final case that throws an exception for an not-allowed ArgType. I'm thinking it would be cleaner to move ArgType to a template parameter, and provide a specialization for each allowed ArgType. Misuse would be caught at compile-time.

推荐答案

在类内部对结构进行部分专业化处理: >

With partial specialization of a structure inside the class:

#include <iostream>

class foo_class
{
    public:
    enum AllowedTypes { T_DOUBLE, T_INT };

    private:
    template <AllowedTypes type, typename T>
    struct AddOneThird;

    template <typename T>
    struct AddOneThird<T_DOUBLE, T> {
        static void apply(T bar) {
            std::cout << "T_DOUBLE specialization: " << bar + 1.0/3.0 << std::endl;
        }
    };

    public:
    template <AllowedTypes type>
    void add_one_third( double bar ) const {
        AddOneThird<type, double>::apply(bar);
    }
};

int main() {
    foo_class a;
    a.add_one_third<foo_class::T_DOUBLE>(3.0);
    // error: incomplete type ‘foo_class::AddOneThird<(foo_class::AllowedTypes)1u
    // a.add_one_third<foo_class::T_INT>(3.0); // should fail at compile-time

    return 0;
}

(朋友)课程的完全专业化:

#include <iostream>

class foo_class
{
    public:
    enum AllowedTypes { T_DOUBLE, T_INT };

    // if needed
    // template<AllowedTypes> friend struct AddOneThird;

    public:
    template <AllowedTypes type> void add_one_third( double bar ) const;
};

template <foo_class::AllowedTypes>
struct AddOneThird;

template <>
struct AddOneThird<foo_class::T_DOUBLE> {
    static void apply(double bar) {
        std::cout << "T_DOUBLE specialization: " << bar + 1.0/3.0 << std::endl;
    }
};

template <foo_class::AllowedTypes type>
void foo_class::add_one_third( double bar) const {
    AddOneThird<type>::apply(bar);
}


int main() {
    foo_class a;
    a.add_one_third<foo_class::T_DOUBLE>(3.0);
    // error: incomplete type ‘AddOneThird<(foo_class::AllowedTypes)1u>’ used
    //        in nested name specifier
    //a.add_one_third<foo_class::T_INT>(3.0); // should fail at compile-time

    return 0;
}

使用C ++ 11或boost :: enable_if:

#include <iostream>
#include <type_traits>

class foo_class
{
    public:
    enum AllowedTypes { T_DOUBLE, T_INT };

    template <AllowedTypes type>
    typename std::enable_if<type == T_DOUBLE>::type
    add_one_third( double bar ) const {
        std::cout << "T_DOUBLE specialization: " << bar + 1.0/3.0 << std::endl;
    }
};

int main() {
    foo_class a;
    a.add_one_third<foo_class::T_DOUBLE>(3.0);
    // error: no matching function for call to ‘foo_class::add_one_third(double)’
    //a.add_one_third<foo_class::T_INT>(3.0); // should fail at compile-time
    return 0;
}

这篇关于仅针对带有枚举非类型模板参数的C ++模板函数的专业化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆