C++ 在现代C+之前,在没有constexpr if的情况下选择性地执行代码+;

C++ 在现代C+之前,在没有constexpr if的情况下选择性地执行代码+;,c++,templates,c++03,C++,Templates,C++03,我想编写一些线程包装器,我需要使用线程参数void*,因为我使用的是非C++11线程库。我偶然发现了一个问题,并准备了一个简单的工作示例。代码如下: #include <iostream> namespace chops { template <typename T, typename U> struct is_same { static const bool value = false; }; template<

我想编写一些线程包装器,我需要使用线程参数
void*
,因为我使用的是非C++11线程库。我偶然发现了一个问题,并准备了一个简单的工作示例。代码如下:

#include <iostream>

namespace chops {
    template <typename T, typename U>
    struct is_same {
        static const bool value = false;
    };

    template<typename T>
    struct is_same<T, T> {
        static const bool value = true;
    };
}

template <typename Functor, typename T>
typename Functor::return_type fun_wrapper(T const& arg) {
    Functor f;
    typename Functor::return_type ret = f(arg);
    return ret;
}

struct hello_world {
    void operator()(int count) {
        while(count--)
            std::cout << "hello, world!\n";
    }
    typedef void return_type;
};

struct is_even {
    bool operator()(int x) {
        if(!(x % 2))
            return true;
        else
            return false;
    }
    typedef bool return_type;
};

int main() {
    //fun_wrapper<hello_world>(3);
    fun_wrapper<is_even>(3);
} 
所以我自己写了一个
是相同的
类型特征,并且只想在
Functor::return\u type
不为空时执行该代码。我想达到这样的效果:

if constexpr(!is_same<Functor::return_type, void>::value) {
    typename Functor::return_type res = f(arg);
    return ret;
} else {
    f(arg);
}
如果constexpr(!is_same::value){
typename函子::return\u type res=f(arg);
返回ret;
}否则{
f(arg);
}
因为我不能使用现代C++,而单独使用C++ 17,我似乎找不到出路。我不知道如何用SFINAE这样的东西达到类似的效果


PS:请注意,这是一个人为的示例,可以进行一些修改,但在我的实际程序中,如果不是无效的,我需要创建一个
Functor::return_type
对象。所以请不要在你的答案中删去这一行。因此,不只是使用
返回f(arg)
最简单的方法是创建两个重载,一个用于当
Functor::return_type
void
时,另一个用于当它不是时。您所要做的就是重新实现
std::enable_if
(例如,在名称空间
chops
):


现场演示。

您可以通过在functor的返回类型上部分专门化类模板来完成此操作(
R
是返回类型,并且只有当返回类型为
void
时,编译器才会选择专门化版本):


一个相当简单的解决方案,基于“现代C++”之前使用的两个技巧:

  • 模板专门化

  • 如果其他方法无效,则使用替换的
    void

  • 样本:

    #include <iostream>
    
    template <typename VALUE>
    struct Property {
      VALUE value;
    
      void set(VALUE value) { this->value = value; }
      const VALUE& get() const { return value; }
    };
    
    struct Void { };
    
    template <>
    struct Property<void>
    {
      void set() { }
      Void get() { return Void(); }
    };
    
    std::ostream& operator<<(std::ostream &out, const Void &value)
    {
      return out;
    }
    
    int main()
    {
      Property<int> propInt;
      propInt.set(123);
      std::cout << propInt.get() << '\n';
      Property<void> propVoid;
      std::cout << propVoid.get() << '\n';
      return 0;
    }
    


    请注意,我用<代码> -STD= C++ 03 编译,尽可能地授予它,它也将在非“现代”C++上工作。

    < P>如果您不需要存储函子返回值,而只返回它自己,则在C++ 03中工作:

    #include <iostream>
    
    template <class Functor, class T>
    typename Functor::return_type fun_wrapper(T const& arg) {
        return Functor()(arg);
    }
    
    struct hello_world {
        void operator()(int count) {
            while(count--)
                std::cout << "hello, world!\n";
        }
        typedef void return_type;
    };
    
    int main() {
        fun_wrapper<hello_world>(3);
    } 
    
    #包括
    样板
    typename Functor::return\u type fun\u包装器(T const&arg){
    返回函子()(arg);
    }
    结构hello_world{
    void运算符()(整数计数){
    而(计数--)
    
    std::cout通常可以涵盖此类情况。我相信这在C++11之前就已经奏效了(例如,在VS2008中,但我已经多年没有使用它)。通过将
    fun_wrapper
    的主体更改为简单的
    函子f;返回f(arg);
    ,可以很容易地修复此示例。顺便说一句,do
    操作符()
    s在您的类中是否真的需要非常量?
    template <typename Functor, typename T>
    typename chops::enable_if<
        !chops::is_same<typename Functor::return_type, void>::value,
        typename Functor::return_type>::type 
    fun_wrapper(T const& arg) {
        Functor f;
        typename Functor::return_type ret = f(arg);
        return ret;
    }
    
    template <typename Functor, typename T>
    typename chops::enable_if<chops::is_same<typename Functor::return_type, void>::value>::type 
    fun_wrapper(T const& arg) {
        Functor f;
        f(arg);
    }
    
    template <typename R, typename Functor, typename T>
    struct fun_wrapper_impl {
        static R wrap(T const& arg) {
            Functor f;
            R ret = f(arg);
            return ret;
        }
    };
    
    template <typename Functor, typename T>
    struct fun_wrapper_impl<void, Functor, T> {
        static void wrap(T const& arg) {
            Functor f;
            f(arg);
        }
    };
    
    template <typename Functor, typename T>
    typename Functor::return_type fun_wrapper(T const& arg) {
        return fun_wrapper_impl<typename Functor::return_type, Functor, T>::wrap(arg);
    }
    
    template <bool V>
    struct tag {};
    
    template <typename Functor, typename T>
    typename Functor::return_type fun_wrapper_impl(T const& arg, tag<false>) {
        Functor f;
        typename Functor::return_type ret = f(arg);
        return ret;
    }
    
    template <typename Functor, typename T>
    void fun_wrapper_impl(T const& arg, tag<true>) {
        Functor f;
        /* returns void */ f(arg);
    }
    
    template <typename Functor, typename T>
    typename Functor::return_type fun_wrapper(T const& arg) {
        tag<chops::is_same<typename Functor::return_type, void>::value> the_tag;
        return fun_wrapper_impl<Functor, T>(arg, the_tag);
    }
    
    #include <iostream>
    
    template <typename VALUE>
    struct Property {
      VALUE value;
    
      void set(VALUE value) { this->value = value; }
      const VALUE& get() const { return value; }
    };
    
    struct Void { };
    
    template <>
    struct Property<void>
    {
      void set() { }
      Void get() { return Void(); }
    };
    
    std::ostream& operator<<(std::ostream &out, const Void &value)
    {
      return out;
    }
    
    int main()
    {
      Property<int> propInt;
      propInt.set(123);
      std::cout << propInt.get() << '\n';
      Property<void> propVoid;
      std::cout << propVoid.get() << '\n';
      return 0;
    }
    
    #include <iostream>
    
    template <class Functor, class T>
    typename Functor::return_type fun_wrapper(T const& arg) {
        return Functor()(arg);
    }
    
    struct hello_world {
        void operator()(int count) {
            while(count--)
                std::cout << "hello, world!\n";
        }
        typedef void return_type;
    };
    
    int main() {
        fun_wrapper<hello_world>(3);
    }