使用std :: conditional中的模板来确定函数参数类型

问题描述 投票:0回答:2

我希望所有的数据保存和加载都经过相同的功能,以减少错误的机会。为此,我使用了许多模板(以及许多函数重载)。它可以正常工作,现在我的代码更加简洁了,但是我无法使用const进行保存(因为它要通过与加载器相同的功能进行操作,在加载器中,数据保持为非const)。

我想正确地使用const,因此这里是尝试使简单版本正常工作的尝试,其中std :: ifstream的数据(在这种情况下为std :: vector)是非const的,否则为const:

#include <iostream>
#include <fstream>
#include <vector>

template <class Foo>
void Overload(const Foo & foo)
{
    std::cout << "went to const" << std::endl;
}

template <class Foo>
void Overload(Foo & foo)
{
    std::cout << "went to non-const" << std::endl;
}

template <class StreamType, typename... Arguments>
void ReadOrWrite (

    /* for 1st argument */ StreamType & filestream,

    /* type for 2nd argument */ typename std::conditional< 
        /* if */    std::is_same<StreamType, std::ifstream>::value,
            /* then */  std::vector<Arguments...>,
            /* else */  const std::vector <Arguments...>
            >::type

        /*2nd argument name */ & vector
        )
{
    Overload(vector);
}

int main ()
{
    std::ofstream output_filestream;
    std::ifstream intput_filestream;

    std::vector<int> vector;

    ReadOrWrite(output_filestream, vector);
    ReadOrWrite(intput_filestream, vector);

    return 0;
}

我知道如果我编辑对此的函数调用,它将正确编译/运行:

ReadOrWrite<std::ofstream, int>(output_filestream, vector);
ReadOrWrite<std::ifstream, int>(intput_filestream, vector);

但是我不希望函数的用户在函数调用期间需要列出类型。

是否有一种干净的方法可以执行我的建议?

c++ oop c++11 vector const
2个回答
2
投票

最好的建议是提供两个分离的功能,因为无论您发送哪种类型的读和写操作都是两个不同的操作。例如,输入和输出都可能是fstream。仅凭类型系统,您就无法知道意图。决定读写是通常的意图,而很少将它们嵌入到类型系统中。

由于保存和加载是不同的操作,因此应该是不同的功能(可能在它们之间共享代码)


如果您确实想要同时执行这两种功能并在类型之间进行切换的功能,那么我建议限制输入或输出的功能:

// input streams
template <class StreamType, typename... Arguments,
    std::enable_if_t<std::is_base_of_v<std::ostream, StreamType>, int> = 0
>
void ReadOrWrite (
    StreamType & filestream,
    std::vector<Arguments...> const& vector
) {
    Overload(vector);
}

// output streams
template <class StreamType, typename... Arguments,
    std::enable_if_t<std::is_base_of_v<std::istream, StreamType>, int> = 0
>
void ReadOrWrite (
    StreamType& inputstream,
    std::vector<Arguments...>& vector
) {
    Overload(vector);
}

由于第二个比第一个更专业,因此只要流为std::istream并且向量是可变的,都将采用它。否则,将采用第一个。

Live example


1
投票

几乎就像您在问题中所写的那样,在辅助函数中,另一个重载解决方案可以转换ReadOrWrite()

template <typename ... Args, typename ST>
void ReadOrWrite_helper (ST &, typename std::conditional<
                                  std::is_same<ST, std::ifstream>::value,
                                  std::vector<Args...>,
                                  std::vector<Args...> const>::type vec)
 { Overload(vec); }

添加一对重载的ReadOrWrite()函数以选择选择Args...并显式调用助手函数

template <typename ... Ts>
void ReadOrWrite (std::ifstream & is, std::vector<Ts...> & vec)
 { ReadOrWrite_helper<Ts...>(is, vec); }

template <typename ... Ts>
void ReadOrWrite (std::ofstream & is, std::vector<Ts...> const & vec)
 { ReadOrWrite_helper<Ts...>(is, vec); }

[注意,由于Args...类型是在非推论上下文中进行说明的,因此,我将它们放在ReadOnWrite_helper()模板参数声明中,before ST;因此也无需明确显示ST

© www.soinside.com 2019 - 2024. All rights reserved.