c++ - multiple overloads of 'Identifier' instantiate to the same signature 'void ()' - Stack Ove

admin2025-04-17  2

template class

template< typename ... Args >
class Identifier: public std::tuple< Args... >
{
public:
   Identifier( Args... args ):std::tuple< Args... >( std::forward< Args >( args )... )
   {}

   Identifier( std::tuple< Args... > tuple ):std::tuple< Args... >( tuple )
   {}

   Identifier()
   {}
};

template< typename ...Args >
inline std::ostream& operator << ( std::ostream& os, Identifier< Args... > const& data )
{
   os << "(";
   /// here code to print Identifier items
   os << ")";
   return os;
}

when I try to print variable

Identifier<std::string, int64_t>  item("str", 10);
std::cout<<item<<std::endl;

I've got a error multiple overloads of 'Identifier' instantiate to the same signature 'void ()'

If I remove constructor

Identifier()
{}

there is no error. But I need this constructor.

So how fix this error ?

template class

template< typename ... Args >
class Identifier: public std::tuple< Args... >
{
public:
   Identifier( Args... args ):std::tuple< Args... >( std::forward< Args >( args )... )
   {}

   Identifier( std::tuple< Args... > tuple ):std::tuple< Args... >( tuple )
   {}

   Identifier()
   {}
};

template< typename ...Args >
inline std::ostream& operator << ( std::ostream& os, Identifier< Args... > const& data )
{
   os << "(";
   /// here code to print Identifier items
   os << ")";
   return os;
}

when I try to print variable

Identifier<std::string, int64_t>  item("str", 10);
std::cout<<item<<std::endl;

I've got a error multiple overloads of 'Identifier' instantiate to the same signature 'void ()'

If I remove constructor

Identifier()
{}

there is no error. But I need this constructor.

So how fix this error ?

Share Improve this question edited Jan 31 at 8:59 Vladimir Shttl asked Jan 31 at 6:47 Vladimir ShttlVladimir Shttl 813 bronze badges 6
  • 4 Can you post a minimal reproducible example not omitting #include and the main function and the complete verbatim error message in a code block? – 3CxEZiVlQ Commented Jan 31 at 6:52
  • Any function (specified with a particular signature - which includes set of arguments types and return type) can only be DEFINED once. If your templated class or function are written in a way that results in any function (template instantiation) being defined more than once, then you break that rule. The reason, in your case, is that parameter packs can be empty (representing no arguments) which gives a constructor of Identifier with no arguments. – Peter Commented Jan 31 at 7:30
  • What exactly is the question? Most likely it is either why you get this error or how to fix it, but which one? (I'm missing one piece for the why -- specifically why Identifier<> needs to be instantiated -- and I don't know if it's worth my time to dig into that more.) – JaMiT Commented Jan 31 at 7:58
  • Okay, weird. This is going to be an example of why a full error message is useful. I noticed a detail in the one from my repro attempt, and I have a way to simplify your minimal reproducible example. Drop item and simply output std::cout<<std::endl;. It's not "when I try to print variable" but when you stream std::endl while the definition of Identifier is in scope. – JaMiT Commented Jan 31 at 8:10
  • 1 @JaMiT interestingly moving the stream insertion into the class also fixes it godbolt.org/z/z5TPrrWzT – Caleth Commented Jan 31 at 10:53
 |  Show 1 more comment

1 Answer 1

Reset to default 2

Your main issue is that Identifier</*Empty*/> has 2 default constructors.

You should restrict the varaidic one:

Identifier(Args... args) requires(sizeof...(Args) != 0) : 
    std::tuple<Args...>(std::forward< Args >(args)...)
{}

Demo

Not clear for me why std::cout<<item<<std::endl; tries to instantiate Identifier</*Empty*/> though.

转载请注明原文地址:http://anycun.com/QandA/1744877541a88892.html