Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/143.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++_Type Safety_Variadic - Fatal编程技术网

C++ 在C+;中,什么是变量函数的良好类型安全替代方案+;?

C++ 在C+;中,什么是变量函数的良好类型安全替代方案+;?,c++,type-safety,variadic,C++,Type Safety,Variadic,与此相结合。对于以下看似基本的问题,我很难想出一个好的类型安全解决方案。我有一个班级音乐播放列表,其中有一个应该播放的歌曲列表。看起来很简单,对吧,只需制作一个包含队列中所有歌曲的std::列表,并让用户可以使用它。然而,出于必要,音频解码和音频渲染在不同的线程上进行。因此,列表需要受到互斥保护。通常情况下,使用我的库的其他程序员会忘记互斥。这显然导致了“奇怪”的问题 所以一开始我只是为这个班写了setter struct music{}; class music_playlist{ priva

与此相结合。对于以下看似基本的问题,我很难想出一个好的类型安全解决方案。我有一个班级音乐播放列表,其中有一个应该播放的歌曲列表。看起来很简单,对吧,只需制作一个包含队列中所有歌曲的std::列表,并让用户可以使用它。然而,出于必要,音频解码和音频渲染在不同的线程上进行。因此,列表需要受到互斥保护。通常情况下,使用我的库的其他程序员会忘记互斥。这显然导致了“奇怪”的问题

所以一开始我只是为这个班写了setter

struct music{};
class music_playlist{
private:
     std::list<music> playlist;
public:
     void add_song(music &song){playlist.push_back(song);}
     void clear(){playlist.clear();}
     void set_list(std::list<music> &songs){playlist.assign(songs.begin(),songs.end());}
//etc
};
现在更容易看到一首歌是被添加了两次还是没有被收录。然而,在解决方案A中,如果NULL不在列表的末尾,并且不是跨平台的,那么它将崩溃。在solutionB中,您必须计算可能导致几个错误的参数数量。此外,没有一个解决方案是类型安全的,用户可以传入一个不相关的类型,并在运行时等待崩溃。这似乎不是一个可持续的解决方案。然后我遇到了std::initializer\u list。无法使用它我开发的一些编译器还不支持它。所以我试着模仿它。我最终得到了下面这个解决方案

这将导致用户代码看起来像这样

struct music_playlist{
    list<music> queue;
//...
};
int main (int argc, const char * argv[])
{
    music_playlist playlist;
    music song1;
    music song2;
    music song3;
    music song4;
    playlist.queue = song1,song2; // The queue now contains song1 and song2
    playlist.queue+= song1,song3,song4; //The queue now contains two song1s and song2-4
    playlist.queue = song2; //the queue now only contains song2
    return 0;
}
这使我对那种解决办法感到厌烦。那么你有没有更好的解决方案


另外,上面的代码都没有被编译过,它们只是出于示例目的。

首先想到的问题是这是否是一个问题,以及这是否是一个值得解决的问题。因为您正在创建一个接口,所以您的客户机将是用户代码(而不是人员代码)。您的客户会在代码中硬编码播放列表多少次,而不是从文件中存储、加载或根据用户选择构建播放列表

思考该功能的实际价值,并将其与用户如何使用您的库的影响进行比较,思考用户在更改界面时可能遇到的问题

最简单的解决方案是接受迭代器来构造/重置列表,然后让用户处理这个问题。当然,他们可以按照您展示的方式构建自己的容器,但他们也可以使用Boost.Assignment来处理锅炉板,因此他们的用户代码如下所示:

std::vector<music> songs = boost::assign::list_of()( song1 )( song2 );
play_list.set( songs.begin(), songs.end() );

老实说,我不明白单行添加
song1、song2、song3、song4、song5、song6
比多行查找错误更好吗?为什么人们会读一本而不读另一本?在我看来,如果您的变量不在列表/数组中,那么您在调用代码中犯了错误,这不是您要解决的问题……您示例中的所有错误都与并发无关,只是编程不好。@LittledV,不幸的是,这是我必须处理的问题。作为该库的目标市场,它具有如此广泛的编程能力。他们中的一些是10年以上的经验领域的专家,而其他人则参与编写他们的第一个C++程序。库的整个设计试图通过简单地浏览源文件,使尽可能多的bug导致编译时错误或易于检测。这是唯一一个我无法应用这种方法的领域。@RTS-只是让我的回答更加有力:假设客户是dumba**-确保你的代码是防污染的。如果需要保护,请自己保护它。至于两次添加同一首歌而错过另一首歌,你真的无能为力。在我看来,两次播放同一首歌是一个可行的用例,所以你不应该因为错误而忽略它。我太累了,无法写出一个实质性的答案,所以我将把这个留在这里。。不要使用逗号运算符,你应该真正坚持标准的
迭代器是最好的解决方案。+1对于Boost.Assign,Boost的另一个很少有人知道的部分。
playlist1.set_listA(&song1,&song2,&song3,&song4,&song5,&song6,NULL);
//playlist1.set_listA(&song1,&song2,&song3,&song4,&song5,&song6); runtime error!!
//or
playlist2.set_listB(6,song1,song2,song3,song4,song5,song6);
struct music_playlist{
    list<music> queue;
//...
};
int main (int argc, const char * argv[])
{
    music_playlist playlist;
    music song1;
    music song2;
    music song3;
    music song4;
    playlist.queue = song1,song2; // The queue now contains song1 and song2
    playlist.queue+= song1,song3,song4; //The queue now contains two song1s and song2-4
    playlist.queue = song2; //the queue now only contains song2
    return 0;
}
//lets combine differnt playlists
new_playlist.queue =    song1        //the first playlist
                      ,(song3,song4) //the second playlist //opps, I didn't add song 3!
                      , song5;
std::vector<music> songs = boost::assign::list_of()( song1 )( song2 );
play_list.set( songs.begin(), songs.end() );
music songs[2] = { song1, song2 };
play_list:set( songs, songs + 2 ); // add your preferred magic to calculate the size