0
template<typename T>
void Func(T& writer)
{
  try
  {
    writer.open("hello.log");
  }
  catch (std::exception & ex) {
    // ...
  }
}

http://en.cppreference.com/w/cpp/types

Question> Is it possible that I can define the template function Func only accepts a type with well-defined open interface?

Thank you

max66
  • 65,235
  • 10
  • 71
  • 111
q0987
  • 34,938
  • 69
  • 242
  • 387
  • 6
    It already will; if you try to provide something that doesn't support `open` with those parameters, it will fail to compile. If you want cleaner error messages, you will need to wait for C++20 [Concepts](http://en.cppreference.com/w/cpp/language/constraints). – 0x5453 Apr 02 '18 at 19:45
  • What is your actual problem? Do you not know how to check if some type has a member function or do you not know how to produce an error message out of that information? – Baum mit Augen Apr 02 '18 at 19:50
  • @BaummitAugen, I want the caller to know that this template function only accepts a type that has a defined `open`. – q0987 Apr 02 '18 at 19:52
  • @q0987 The compiler will tell them as it stands. I still don't know what you are trying to achieve. What does / doesn't it do now that it should not / should? – Baum mit Augen Apr 02 '18 at 19:54
  • @BaummitAugen, https://stackoverflow.com/questions/874298/c-templates-that-accept-only-certain-types, basically, I wanted to add some traits information so that the caller doesn't have to compile the code before they know that the type must have a defined `open` API. – q0987 Apr 02 '18 at 19:57
  • 2
    So, just use a comment. The language stuff gets enforced by the compiler and is, as you don't want to use it, of no use here. – Baum mit Augen Apr 02 '18 at 20:04
  • @BaummitAugen, I just made things a little complicated than it should be. Thank you for your help. – q0987 Apr 02 '18 at 20:21

1 Answers1

1

Not clear why do you want to do this but... if you declare (no needs to define) a couple of helper functions

template <typename T, typename ... Args>
constexpr auto withOpenHelper (int)
   -> decltype(std::declval<T>().open(std::declval<Args>()...),
               std::true_type{} );

template <typename ... Args>
constexpr std::false_type withOpenHelper (long);

and a using to simplify the use

template <typename T, typename ... Args>
using withOpen = decltype( withOpenHelper<T, Args...>(0) );

you can SFINAE enable/disable Func() only if T support a open() receiving a std::string

template <typename T>
std::enable_if_t<withOpen<T, std::string>::value> Func (T & writer)
 {
   // something
 }

The following is a full working example

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

struct A { int open (std::string const &) { return 0; } };
struct B {  };

template <typename T, typename ... Args>
constexpr auto withOpenHelper (int)
   -> decltype(std::declval<T>().open(std::declval<Args>()...),
               std::true_type{} );

template <typename ... Args>
constexpr std::false_type withOpenHelper (long);

template <typename T, typename ... Args>
using withOpen = decltype( withOpenHelper<T, Args...>(0) );

template <typename T>
std::enable_if_t<withOpen<T, std::string>::value> Func (T & writer)
 {
      writer.open("hello.log");
 }

int main ()
 {
   A a;
   B b;

   Func(a);
   //Func(b); // compilation error
 }
max66
  • 65,235
  • 10
  • 71
  • 111
  • 2
    Not sure how this would be better than what they already have. – Baum mit Augen Apr 02 '18 at 20:22
  • 1
    @BaummitAugen You can `static_assert` with cleaner error message. – Zereges Apr 02 '18 at 20:28
  • @BaummitAugen - so do I... I don't understand what exactly want the OP... but I suppose that, this way, he can develop different `Func()` functions for different types (one for classes with `open()` with a `std::string` argument, one for classes with `open()` with two `int` arguments, one for classes with `open2()`, etc.) – max66 Apr 02 '18 at 20:37