Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/139.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++:如果std::is_basical:在MSVC 2010中用于条件编译的值,则使用_C++_Conditional Compilation_Typetraits - Fatal编程技术网

C++:如果std::is_basical:在MSVC 2010中用于条件编译的值,则使用

C++:如果std::is_basical:在MSVC 2010中用于条件编译的值,则使用,c++,conditional-compilation,typetraits,C++,Conditional Compilation,Typetraits,在我的模板中,我需要根据typename是否为基本类型而拥有不同的代码部分 编译此代码将在MSVC中提供一个C4067意外标记,该标记遵循预处理器指令-应为换行符: template <typename T> void MyClass<T>::foo() { // ... some code here #if std::is_fundamental<T>::value if(m_buf[j] < m_buf[idx_min]) i

在我的模板中,我需要根据typename是否为基本类型而拥有不同的代码部分

编译此代码将在MSVC中提供一个C4067意外标记,该标记遵循预处理器指令-应为换行符:

template <typename T>
void MyClass<T>::foo()
{
// ... some code here
#if std::is_fundamental<T>::value
    if(m_buf[j] < m_buf[idx_min])
        idx_min = j;
#else
    const ASSortable& curr = dynamic_cast<ASSortable&>(m_buf[j]);
    const ASSortable& curr_min = dynamic_cast<ASSortable&>(m_buf[idx_min]);
    // error checking removed for simplicity
    if(curr.before(curr_min))
        idx_min = j;
}
#endif
该模板将同时使用从可分类数据类型派生的primitive和my own,错误来自模板实例化代码:

template class MyClass<char>;
尝试将预编译器表达式修改为该表达式也不起作用:

#if std::is_fundamental<T>::value == true
并产生相同的确切警告

有没有办法让这段代码无警告

编辑我想到的另一件事是将其转换为运行时检查,并使用常量if表达式警告。。。真的没有办法在没有专门化和额外膨胀的单个函数中优雅地实现这一点吗

编辑2所以我解决这个问题的方法是显而易见的,但不知怎的我逃过了。。。是在_o;}之前定义布尔可分类::运算符;它完成了任务并使代码再次干净

我的代码中不再有ifs或IFDEF或任何类似的混乱


我甚至不敢相信我问了这个问题,因为它有一个如此明显和简单的答案:

预处理器是在编译的早期阶段运行的,在编译器分析类型并了解std::is_basical::value的含义之前,因此它不能以这种方式工作

相反,使用专门化:

template<bool> void f();

template<> void f<true>() {
    if(m_buf[j] < m_buf[idx_min])
        idx_min = j;
}

template<> void f<false>() {
    const ASSortable& curr = dynamic_cast<ASSortable&>(m_buf[j]);
    const ASSortable& curr_min = dynamic_cast<ASSortable&>(m_buf[idx_min]);
    // error checking removed for simplicity
    if(curr.before(curr_min))
        idx_min = j;
}

template <typename T>
void MyClass<T>::foo()
{
// ... some code here
    f<std::is_fundamental<T>::value>();
}

预处理器在编译的早期阶段运行,在编译器分析类型并了解std::is_basical::value的含义之前,因此它不能以这种方式工作

相反,使用专门化:

template<bool> void f();

template<> void f<true>() {
    if(m_buf[j] < m_buf[idx_min])
        idx_min = j;
}

template<> void f<false>() {
    const ASSortable& curr = dynamic_cast<ASSortable&>(m_buf[j]);
    const ASSortable& curr_min = dynamic_cast<ASSortable&>(m_buf[idx_min]);
    // error checking removed for simplicity
    if(curr.before(curr_min))
        idx_min = j;
}

template <typename T>
void MyClass<T>::foo()
{
// ... some code here
    f<std::is_fundamental<T>::value>();
}

这和它说的差不多,不能在预处理器指令中使用::。实际上,if之后唯一可以使用的是编译时之前定义的常量表达式。您可以找到一些信息

它几乎就是它所说的,您不能在预处理器指令中使用::。实际上,if之后唯一可以使用的是编译时之前定义的常量表达式。您可以找到一些信息,std::is_basical::value==true不能在预处理时使用。我想如果出现以下情况,您将不得不对std::enable_使用一些SFINAE技巧:

template <typename T>
typename std::enable_if<std::is_fundamental<T>::value, void>::type 
MyClass<T>::foo()
{
    // ... some code here

    if(m_buf[j] < m_buf[idx_min])
        idx_min = j;
}


template <typename T>
typename std::enable_if<!std::is_fundamental<T>::value, void>::type 
MyClass<T>::foo()
{
    // ... some code here

    const ASSortable& curr = dynamic_cast<ASSortable&>(m_buf[j]);
    const ASSortable& curr_min = dynamic_cast<ASSortable&>(m_buf[idx_min]);
    // error checking removed for simplicity
    if(curr.before(curr_min))
        idx_min = j;
}
std::is_basical::value==true不能在预处理时使用。我想如果出现以下情况,您将不得不对std::enable_使用一些SFINAE技巧:

template <typename T>
typename std::enable_if<std::is_fundamental<T>::value, void>::type 
MyClass<T>::foo()
{
    // ... some code here

    if(m_buf[j] < m_buf[idx_min])
        idx_min = j;
}


template <typename T>
typename std::enable_if<!std::is_fundamental<T>::value, void>::type 
MyClass<T>::foo()
{
    // ... some code here

    const ASSortable& curr = dynamic_cast<ASSortable&>(m_buf[j]);
    const ASSortable& curr_min = dynamic_cast<ASSortable&>(m_buf[idx_min]);
    // error checking removed for simplicity
    if(curr.before(curr_min))
        idx_min = j;
}

您正在混淆编译状态。预处理器在实际编译器之前运行,不知道类型或模板。它只是执行非常复杂的文本替换

<>当前C++中没有静态IF1,所以你必须求助于一种不同的方法来进行条件编译。对于函数,如果需要,我更愿意启用

1参考文献:

:静态,如果由Alexandrescu以本机形式呈现

:Walter E.Brown关于静态if的建议


:Sutter、Bright和Alexandrescu关于静态if的建议,如果您混淆了编译状态。预处理器在实际编译器之前运行,不知道类型或模板。它只是执行非常复杂的文本替换

<>当前C++中没有静态IF1,所以你必须求助于一种不同的方法来进行条件编译。对于函数,如果需要,我更愿意启用

1参考文献:

:静态,如果由Alexandrescu以本机形式呈现

:Walter E.Brown关于静态if的建议


:Sutter、Bright和Alexandrescu关于静态if的建议解决该问题的常见模式是将函数移动到一个专门化的基类,并滥用继承将其纳入您的范围:

template <typename T, bool is_fundamental>
struct Foo_impl {
   void foo() {
   }
};
template <typename T>
struct Foo_impl<T,true>
{
   void foo() {              // is fundamental version
   }
};
template <typename T>
class Foo : public Foo_impl<T, std::is_fundamental_type<T>::value> {
   // ...
};
该解决方案允许用户编写如下代码:

Foo<int> f;
f.foo<std::string>();

它将实例化一个您不需要也不想要的函数,并将执行您不想要的逻辑。即使用户不想愚弄您的类,但接口中的模板这一事实可能会令人困惑,并使用户认为可以为不同的类型调用它。

解决该问题的常见模式是将函数移动到专用的基类,并滥用继承将其带到您的范围:

template <typename T, bool is_fundamental>
struct Foo_impl {
   void foo() {
   }
};
template <typename T>
struct Foo_impl<T,true>
{
   void foo() {              // is fundamental version
   }
};
template <typename T>
class Foo : public Foo_impl<T, std::is_fundamental_type<T>::value> {
   // ...
};
该解决方案允许用户编写如下代码:

Foo<int> f;
f.foo<std::string>();

它将实例化一个您不需要也不想要的函数,并将执行您不想要的逻辑。即使用户不想愚弄您的类,但界面中的模板可能会让人困惑,并让用户认为可以为不同的类型调用它。

您不能使用MyClass的专门化吗?我正在尝试不要用太多的专门化来污染实现。考虑到MyClass将专门为一些基本类型和代码变得混乱的方式太快专业化将覆盖char /短/ int / long / long long和它们的未签名的对应,浮动/双/长双,所以我真的宁愿只是有条件编译而不是COPYI。
为基本类的每个特殊化生成代码块type@YePhIcK您可以始终使用enable_if来防止为一个专用重载专门化类。我的解决方案就是这么做的。下面所有的解决方案都是有效的,但我最终可能不会使用它们中的任何一个,原因如下:调试程序的难度至少是编写程序的两倍,所以如果你在能力极限下编写程序。。。我相信简单的代码不需要专家级的阅读/理解。可惜我的问题没有优雅的解决方案。你为什么还要定义一个可分类的接口?我们已经有了Operator,你能不能使用MyClass的专门化?我尽量不让太多的专门化污染实现。考虑到MyClass将专门用于一些基本类型,并且代码变得混乱的方式太快专业化将覆盖char /短/ int /长/长朗及其未签名的对应项,float/double/long-double,所以我真的更愿意只进行条件编译,而不是为基本类的每个专门化复制代码块type@YePhIcK您可以始终使用enable_if来防止为一个专用重载专门化类。我的解决方案就是这么做的。下面所有的解决方案都是有效的,但我最终可能不会使用它们中的任何一个,原因如下:调试程序的难度至少是编写程序的两倍,所以如果你在能力极限下编写程序。。。我相信简单的代码不需要专家级的阅读/理解。可惜我的问题没有优雅的解决方案。你为什么还要定义一个可分类的接口?我们已经有了operatorAfaik,除非您使foo依赖于模板参数,否则这将不起作用。好吧,除非您使foo依赖于模板参数,否则这将不起作用。是的,这是我的解决方案的一个真正问题。您的API更安全、更干净。是的,这是我的解决方案的一个真正问题。你的API更安全、更干净。太糟糕了,静态if很快就不可用:@YePhIcK:static if自身也有问题。它将允许某些结构,这些结构可能会让用户感到困惑,并且很难被编译器跟踪。我记不起细节,但它归结为这样一个事实:在模板实例化第二阶段的查找之前,类型的实际内容是未知的,如果static if语句可能会更改某些字段或属性。如果static if很快就不可用,@YePhIcK:static if自身存在问题。它将允许某些结构,这些结构可能会让用户感到困惑,并且很难被编译器跟踪。我想不起细节,但归根结底,在模板实例化第二阶段查找之前,类型的实际内容是未知的,如果statements@DavidRodríguez dribeas:不正确,除非你显式地实例化它们,否则它们不会被实例化。对不起,我不知道我在想什么。@DavidRodríguez dribeas:不正确,除非你显式地实例化它们,否则它们不会被实例化。对不起,我不知道我在想什么。