Noa*_*ahR 1 c++ enums static-assert template-specialization
这个问题关系到这一个除了不是处理类型名称的模板参数,我想使用一个枚举非类型模板参数.
是否有可能只有特化的模板化(类成员函数),在非类型模板参数的情况下没有通用(工作)定义?
通过在类体中声明并仅提供特化,我能够使一个版本工作,但是任何使用非定义模板参数的误操作都不会产生错误,直到链接.更糟糕的是,缺失的符号隐含地指的是枚举的整数值而不是它的名称,所以它会让其他开发人员感到困惑.
我能够BOOST_STATIC_ASSERT从引用的问题中获取技术仅适用于typename模板参数.
此代码演示了这个想法.我不希望CAT-version调用编译:
#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;
}
Run Code Online (Sandbox Code Playgroud)
背景: 我有一个类成员函数,它采用枚举"ArgType"和名称.
void declareKernelArgument( ArgType type, std::string name );
Run Code Online (Sandbox Code Playgroud)
该定义已经变成了if..else..if..else大约六个允许的ArgType案例的列表.我还必须有最终案例,为不允许的ArgType抛出异常.我认为将ArgType移动到模板参数会更加清晰,并为每个允许的ArgType提供特化.滥用将在编译时捕获.
小智 6
对类中的结构进行部分特化:
#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;
}
Run Code Online (Sandbox Code Playgroud)
完全专业化(朋友)课程:
#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;
}
Run Code Online (Sandbox Code Playgroud)
使用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;
}
Run Code Online (Sandbox Code Playgroud)