C++ 构造函数参数的所有组合

C++ 构造函数参数的所有组合,c++,C++,很可能是一个愚蠢的问题,但不管怎么说,这就是问题所在 有没有一种简单的方法来声明可以接受任何参数组合的构造函数?例如,具有3个参数的ctor有2^3种可能的组合(如下面的模型所示) 模板 结构节点{ 节点(物种sp,边边,T数据):sp_m(sp),边_m(边),数据_m(数据){} //默认Ctor,0参数 Node():节点(物种(),边缘(),T()){} //1 arg的所有组合 节点(物种sp):节点(sp,Edge(),T()){} 节点(边):节点(种类(),边,T()){} 节点

很可能是一个愚蠢的问题,但不管怎么说,这就是问题所在

有没有一种简单的方法来声明可以接受任何参数组合的构造函数?例如,具有3个参数的ctor有2^3种可能的组合(如下面的模型所示)

模板
结构节点{
节点(物种sp,边边,T数据):sp_m(sp),边_m(边),数据_m(数据){}
//默认Ctor,0参数
Node():节点(物种(),边缘(),T()){}
//1 arg的所有组合
节点(物种sp):节点(sp,Edge(),T()){}
节点(边):节点(种类(),边,T()){}
节点(T数据):节点(物种(),边缘(),数据){}
//2个参数的所有组合
节点(物种sp,边缘):节点(sp,边缘,T()){}
节点(物种sp,T数据):节点(sp,Edge(),data){}
节点(边,T数据):节点(物种(),边,数据){}
种属;
边缘m;
T数据;
};

我可以避免声明所有不同的CTOR吗?

我不会通过构造函数,而是通过重载,比如操作符来实现,您可以使用默认参数:

template<typename T>
struct Node{
    explicit Node(Species sp = Species(), Edge edge = Edge(), T data = T()) :
        sp_m(sp), edge_m(edge), data_m(data) { }

    Species sp_m;
    Edge    edge_m;
    T       data_m;
};
您不能执行以下操作:

Node<int> x6 = Node<int>(i);
节点x6=节点(i);
不过,这可能没关系,因为在以下情况下,在调用哪个构造函数时会有歧义:

Node<Species> x6 = Node<Species>(s);
节点x6=节点;

< > >代码> S/<代码>指定<代码> sp <代码>参数或<代码>数据< /代码>参数>

您可以考虑一些类似Fluent生成器的东西。(在这里,我省略了使用模板来简化图片,但我认为您可以自己在生成器中添加模板参数:

(psuedo代码)

因此,您的构造代码应该如下所示:

Node node = NodeBuilder.newBuilder()
              .withSpices(someSpices)
              .withData(someData)
              .toNode();

还有一个选项-使用Boost参数库使用命名参数和默认值,以便您可以指定1、2或3个参数。这种方法的一个优点是您可以按任何顺序提供它们。有关更多信息,请参阅。

使用SFINAE的其他方法。
奖励:所有参数顺序都可以。
T
的相同限制:既不能是
Specie
也不能是
Edge

#include <tuple>

// count the number of T in Ts...
template <typename T, typename ...Ts> struct count_type;

template <typename T, typename Tail, typename ...Ts>
struct count_type<T, Tail, Ts...>
{
    constexpr static int value = std::is_same<T, Tail>::value + count_type<T, Ts...>::value;
};
template <typename T> struct count_type<T> { constexpr static int value = 0; };

// index of T in Ts..., or -1 if not found
template <typename T, typename ... Ts> struct get_index;

template <typename T> struct get_index<T> { static const int value = -1; };

template <typename T, typename ... Ts> struct get_index<T, T, Ts...> { static const int value = 0; };

template <typename T, typename Tail, typename ... Ts>
struct get_index<T, Tail, Ts...>
{
    static const int value =
        get_index<T, Ts...>::value == -1 ? -1 : 1 + get_index<T, Ts...>::value;
};

// similar to get<T>(tuple), but return T{} if not found
template <typename T, int N, typename ... Ts>
struct get_helper
{
    static T get(const std::tuple<const Ts&...>& t) { return std::get<N>(t); }
};

template <typename T, typename ... Ts>
struct get_helper<T, -1, Ts...>
{
    static T get(const std::tuple<const Ts&...>& t) { return T{}; }
};

// similar to get<T>(tuple), but return T{} if not found
template <typename T, typename ... Ts>
T get_or_construct(const std::tuple<const Ts&...>& t)
{
    return get_helper<T, get_index<T, Ts...>::value, Ts...>::get(t);
}


class Species {};
class Edge {};

template<typename T>
struct Node{
    Node(const Species& sp, const Edge& edge, T data) : sp_m(sp), edge_m(edge), data_m(data) { }

    template <typename ... Ts>
    Node(const Ts&... ts) : Node(std::tie(ts...)) {}

private:
    template <typename ... Ts, typename =
        typename std::enable_if<count_type<Species, Ts...>::value <= 1
                                && count_type<Edge, Ts...>::value <= 1
                                && count_type<T, Ts...>::value <= 1>::type>
    Node(const std::tuple<const Ts&...>& t) :
        Node(get_or_construct<Species>(t),
             get_or_construct<Edge>(t),
             get_or_construct<T>(t))
    {}

private:
    Species sp_m;
    Edge    edge_m;
    T       data_m;
};

int main(int argc, char *argv[])
{
    Node<int> n(Species {}, Edge{}, 42); // normal constructor
    Node<int> n2(Species {}, 42);        // template constructor
    return 0;
}
#包括
//计算T中的T数。。。
模板结构计数类型;
模板
结构计数类型
{
constexpr static int value=std::is_same::value+count_type::value;
};
模板结构计数\u类型{constexpr static int value=0;};
//Ts中T的索引…,如果未找到,则为-1
模板结构获取索引;
模板结构get_index{static const int value=-1;};
模板结构get_索引{static const int value=0;};
模板
结构获取索引
{
静态常量int值=
获取索引::值==-1?-1:1+获取索引::值;
};
//与get(tuple)类似,但如果未找到,则返回T{}
模板
结构获取辅助程序
{
静态T get(const std::tuple&T){return std::get(T);}
};
模板
结构获取辅助程序
{
静态T get(const std::tuple&T){return T{};}
};
//与get(tuple)类似,但如果未找到,则返回T{}
模板
T获取或构造(const std::tuple&T)
{
返回get\u helper::get(t);
}
类群种{};
类边{};
模板
结构节点{
节点(常数物种和sp,常数边和边,T数据):sp_m(sp),Edge_m(Edge),data_m(data){
模板
节点(const Ts&…Ts):节点(std::tie(Ts…){
私人:

模板我认为“不能跳过参数”违背了目的。@BenVoigt可能…如果是这样的话,那么还有其他答案没有这个限制。@LightnessRacesinOrbit lol,我不知道为什么我写了这个…现在修复+1,尽管在答案中获得更多细节会很好。谢谢,好吧,这里我指的是这里。不是在远程位置此外,如果能看到一个与问题中的代码实际相关的具体(完整)示例,那就太好了。@DavidNeiss我在这里支持jogojapan。如果能看到一个基于问题的示例,那就太好了…+1.Thx,我不知道这种模式。不过,我需要一段时间来消化它。
Node<int> x6 = Node<int>(i);
Node<Species> x6 = Node<Species>(s);
// Have only 1 ctor for Node, or simply no ctor as it is a struct

struct Node {
   Species m_sp;
   Edge    m_edge;
   Data    m_data;
   Node(Species& sp, Edge& edge, Data& data) : m_sp(sp), m_edge(edge), m_data(data) { }
};

class NodeBuilder {
private:
  Species* m_species;
  Edge* m_edge;
  Data* m_data;

public:
  static NodeBuilder& newBuilder() {
    return NodeBuilder();
  }

  void withSpecies(Species& species) {
    m_species= &species;
  }
  void withEdge(Edge& edge) {
    m_edge = &edge;
  }
  void withData(Data& data) {
    m_data = data;
  }
  void Node& toNode() {
    return Node(m_species? (*m_species) : Species(), 
                m_edge? (*edge) : Edge(),
                m_data? (*data) : Data());
  }
};
Node node = NodeBuilder.newBuilder()
              .withSpices(someSpices)
              .withData(someData)
              .toNode();
#include <tuple>

// count the number of T in Ts...
template <typename T, typename ...Ts> struct count_type;

template <typename T, typename Tail, typename ...Ts>
struct count_type<T, Tail, Ts...>
{
    constexpr static int value = std::is_same<T, Tail>::value + count_type<T, Ts...>::value;
};
template <typename T> struct count_type<T> { constexpr static int value = 0; };

// index of T in Ts..., or -1 if not found
template <typename T, typename ... Ts> struct get_index;

template <typename T> struct get_index<T> { static const int value = -1; };

template <typename T, typename ... Ts> struct get_index<T, T, Ts...> { static const int value = 0; };

template <typename T, typename Tail, typename ... Ts>
struct get_index<T, Tail, Ts...>
{
    static const int value =
        get_index<T, Ts...>::value == -1 ? -1 : 1 + get_index<T, Ts...>::value;
};

// similar to get<T>(tuple), but return T{} if not found
template <typename T, int N, typename ... Ts>
struct get_helper
{
    static T get(const std::tuple<const Ts&...>& t) { return std::get<N>(t); }
};

template <typename T, typename ... Ts>
struct get_helper<T, -1, Ts...>
{
    static T get(const std::tuple<const Ts&...>& t) { return T{}; }
};

// similar to get<T>(tuple), but return T{} if not found
template <typename T, typename ... Ts>
T get_or_construct(const std::tuple<const Ts&...>& t)
{
    return get_helper<T, get_index<T, Ts...>::value, Ts...>::get(t);
}


class Species {};
class Edge {};

template<typename T>
struct Node{
    Node(const Species& sp, const Edge& edge, T data) : sp_m(sp), edge_m(edge), data_m(data) { }

    template <typename ... Ts>
    Node(const Ts&... ts) : Node(std::tie(ts...)) {}

private:
    template <typename ... Ts, typename =
        typename std::enable_if<count_type<Species, Ts...>::value <= 1
                                && count_type<Edge, Ts...>::value <= 1
                                && count_type<T, Ts...>::value <= 1>::type>
    Node(const std::tuple<const Ts&...>& t) :
        Node(get_or_construct<Species>(t),
             get_or_construct<Edge>(t),
             get_or_construct<T>(t))
    {}

private:
    Species sp_m;
    Edge    edge_m;
    T       data_m;
};

int main(int argc, char *argv[])
{
    Node<int> n(Species {}, Edge{}, 42); // normal constructor
    Node<int> n2(Species {}, 42);        // template constructor
    return 0;
}