2

I am attempting to make a print function that functions like a python print function, and I am having issues with enforcing what type the variadic arguments can be, I would like them to be restricted to const char*.

Here is my code so far:

#include <tuple>
#include <iostream>
#include <utility>
#include <type_traits>


template<
  std::size_t I=0,
  typename... Args,
  typename FUNCTION
  >
constexpr void for_each(const std::tuple<Args...>& t, FUNCTION &&func)
{
  if constexpr(I < sizeof...(Args))
  {
    func(std::get<I>(t));
    for_each<I + 1>(t, std::forward<FUNCTION>(func));
  }
}

template<
  typename... Args
  >
constexpr void print(Args... args)
{
  std::tuple t(std::forward<Args>(args)...);
  for_each(t, [=](const char* str)
  {
    std::cout << str << " ";
  });
  std::cout << '\n';
}

int main(void)
{
  print("this", "is", "a", "thing");
  print("this", "is", "not", "a", "thing");
  return 0;
}

I would like the variadic template argument in the print function to only accept const char*

2
  • 1
    Why would you limit yourself so? If you change [=](const char* str) to [=](const auto& elem ) your lambda can work with any type that has defined operator <<. Commented Jul 7, 2020 at 12:29
  • FYI this is already done: fmt. Commented Jul 7, 2020 at 12:32

2 Answers 2

5

You don't need std::tuple to do that and you can restrict your function to copy const char* only using std::enable_if, as follows

#include <iostream>
#include <type_traits>


template<typename ... Args>
constexpr std::enable_if_t<std::is_same_v<std::common_type_t<Args...>,const char*>, void>
print(Args&&... args)
{
    ((std::cout << args << " "),...);
    std::cout << '\n';
}
int main( )
{
    print("this", "is", "a", "thing");
    print("this", "is", "not", "a", "thing");
    print(5, "is", "not", "a", "thing");//compile error
    return 0;
}
Sign up to request clarification or add additional context in comments.

2 Comments

thanks for the fast answer, will this produce a substitution failure or will it just fail to compile?
@finlaymorrison print(5, "is", "not", "a", "thing"); will prevent your compiler to compile the whole program
2

If you really want to accept only const char* you can do it like this, using static_assert (if you have C++17 support):

template<typename... Args>
constexpr void print(Args... args) {
  static_assert((std::is_same_v<Args, const char*> && ...), "Your pretty error message");
  std::tuple t(std::forward<Args>(args)...);
  for_each(t, [=](const char* str)
  {
    std::cout << str << " ";
  });
  std::cout << '\n';
}

4 Comments

Thanks for the fast answer, i'll try implementing this.
What for_each overload is that? It looks wicked and nice. I found this implementation when looking for it.
@TedLyngmo its OP's for_each
@bartop Facepalm... I need to read more carefully :-) So, there - you also got a vote.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.