Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/151.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++ 如何检查类是否具有特定的函数以避免编译时问题?_C++_C++11_Templates_Compiler Errors - Fatal编程技术网

C++ 如何检查类是否具有特定的函数以避免编译时问题?

C++ 如何检查类是否具有特定的函数以避免编译时问题?,c++,c++11,templates,compiler-errors,C++,C++11,Templates,Compiler Errors,我有两个类A和B,一个共同的函数在它们上面做一些操作,只是有一个微小的区别 我试过使用std::is_same,但它似乎无法防止编译时问题 class A { public: void aSpecificFunctionToA() { } }; class B { }; template<typename T> void someFunction(T obj) { if(std::is_same<T, A>::value) {

我有两个类A和B,一个共同的函数在它们上面做一些操作,只是有一个微小的区别

我试过使用std::is_same,但它似乎无法防止编译时问题

class A {
public: 
    void aSpecificFunctionToA() {
    }
};

class B {
};


template<typename T>
void someFunction(T obj) {
    if(std::is_same<T, A>::value)
    {
        obj.aSpecificFunctionToA();
    }
}
A类{
公众:
void aSpecificFunctionToA(){
}
};
B类{
};
模板
空函数(T obj){
if(std::is_same::value)
{
obj.aspecificsfunctiontoa();
}
}

如何处理这种情况?

如果可以使用c++17,那么如果满足某些约束,则可以使用
If constexpr
有条件地编译代码

template<typename T>
void someFunction(T obj) {
    if constexpr (std::is_same<T, A>::value)
    {
        obj.aSpecificFunctionToA();
    }
    // ... code for all Ts
}

这段代码阻止编译器基于const bool表达式构建特定的if块

const bool flag = std::is_same<T, A>::value;
#if(flag)
{
    obj.aSpecificFunctionToA();
}
#endif
const bool flag=std::is_same::value;
#国际单项体育联合会(旗)
{
obj.aspecificsfunctiontoa();
}
#恩迪夫

如果您有多个类具有
aSpecificFunctionToA
(在本例中,名称选择不当),则可以使用SFINAE

完整的C++11:

#include <vector>
#include <functional>
#include <iostream>
#include <memory>
#include <type_traits>

namespace detail_traits
{
template <class...>
struct Args
{
};

template <class... T>
using void_t = void;

template <class T, class args, class = void>
struct has_aSpecificFunctionToA : std::false_type
{
};
template <class T, class... args>
struct has_aSpecificFunctionToA<
    T,
    Args<args...>,
    void_t<decltype(std::declval<T>().aSpecificFunctionToA(std::declval<args>()...))>> : std::true_type
{
};

} // namespace detail_traits
template <class T, class... Args>
using has_aSpecificFunctionToA = typename detail_traits::has_aSpecificFunctionToA<T, detail_traits::Args<Args...>>;


class A
{
  public:
    void aSpecificFunctionToA() {
    std::cout << "aSpecificFunctionToA" << std::endl;
    }
};

class B
{
};

template <typename T>
typename std::enable_if<has_aSpecificFunctionToA<T>::value>::type someFunction(T obj)
{
        obj.aSpecificFunctionToA();
}

template <typename T>
typename std::enable_if<!has_aSpecificFunctionToA<T>::value>::type someFunction(T )
{
        std::cout << "some code for class without aSpecificFunctionToA" << std::endl;
}

int main()
{
    std::cout << has_aSpecificFunctionToA<A>::value << std::endl;
    std::cout << has_aSpecificFunctionToA<B>::value << std::endl;

    someFunction(A{});
    someFunction(B{});
}
#包括
#包括
#包括
#包括
#包括
名称空间详细信息
{
模板
结构参数
{
};
模板
使用void\u t=void;
模板
结构的\u特定函数为:std::false \u类型
{
};
模板
结构具有\u特定的功能<
T
Args,
void\u t>:std::true\u类型
{
};
}//名称空间详细信息\u特征
模板
使用has\u aSpecificFunctionToA=typename detail\u traits::has\u aSpecificFunctionToA;
甲级
{
公众:
void aSpecificFunctionToA(){

std::cout::value我更喜欢简单的老式解决方案:


<代码> >定义日志STD::CUT需要一个这样的设计,这通常是糟糕的设计。考虑使用函数重载来代替特定类型的事物。@某个程序员可以明确为什么它是一个糟糕的设计吗?因为它不是API的一部分,它可能会让用户感到惊讶。我使用的函数有长代码,这个变化只针对1个特定的F。函数。我想重新编写整个代码将是一个糟糕的设计,因为代码将是多余的。如果我错了,请纠正我。@MartinMorterol对类型的显式选择(如问题中所述)可能很快变得毛茸茸的,难以阅读和理解,因此也难以维护。使用语言本身的类型选择(重载)使代码更清晰、更清晰、更易于维护。预处理器指令(如
#if
)在实际编译代码之前进行处理。这意味着预处理器对变量一无所知,至少不知道它们的所有值(即使它们是编译时常量)。
#include <vector>
#include <functional>
#include <iostream>
#include <memory>
#include <type_traits>

namespace detail_traits
{
template <class...>
struct Args
{
};

template <class... T>
using void_t = void;

template <class T, class args, class = void>
struct has_aSpecificFunctionToA : std::false_type
{
};
template <class T, class... args>
struct has_aSpecificFunctionToA<
    T,
    Args<args...>,
    void_t<decltype(std::declval<T>().aSpecificFunctionToA(std::declval<args>()...))>> : std::true_type
{
};

} // namespace detail_traits
template <class T, class... Args>
using has_aSpecificFunctionToA = typename detail_traits::has_aSpecificFunctionToA<T, detail_traits::Args<Args...>>;


class A
{
  public:
    void aSpecificFunctionToA() {
    std::cout << "aSpecificFunctionToA" << std::endl;
    }
};

class B
{
};

template <typename T>
typename std::enable_if<has_aSpecificFunctionToA<T>::value>::type someFunction(T obj)
{
        obj.aSpecificFunctionToA();
}

template <typename T>
typename std::enable_if<!has_aSpecificFunctionToA<T>::value>::type someFunction(T )
{
        std::cout << "some code for class without aSpecificFunctionToA" << std::endl;
}

int main()
{
    std::cout << has_aSpecificFunctionToA<A>::value << std::endl;
    std::cout << has_aSpecificFunctionToA<B>::value << std::endl;

    someFunction(A{});
    someFunction(B{});
}