Почему термин не оценивает функцию, принимающую 0 аргументов? - PullRequest
4 голосов
/ 06 января 2012

Когда я пытаюсь скомпилировать

template<bool val>
struct boolean { static const bool value = val; };

template<typename T>
struct is_callable : boolean<sizeof((*(T*)0)()) >= 0> { };            // error!

int main(void) { bool b = is_callable<int (*)()>::value; }

, я получаю:

error C2064: term does not evaluate to a function taking 0 arguments  
    see reference to class template instantiation 'is_callable<T>' being compiled

Я почти уверен, int (*)() может вызываться с 0 аргументами ... так почему же нетт этой компиляции?

Ответы [ 3 ]

0 голосов
/ 02 февраля 2012

Для меня это работает.

    typedef int (*X)();

    template<typename T>
    struct is_callable : boolean<sizeof((*(X*)(T*)0)()) >= 0> { };            // works!

Таким образом, похоже, что компилятор не уверен, что вы всегда будете передавать указатель на функцию T при создании экземпляра класса шаблона! Итак, форсируем компилятор с явным приведением.

[Редактировать]: Кроме того, если подумать, я не понимаю, что вы на самом деле пытаетесь сделать. Вы пытаетесь измерить размер указателя функции, который принимает один параметр? Как это будет отличаться для функций с разными типами возвращаемых значений? Зачем вам вообще нужен шаблон для константного выражения (например, sizeof (void *))?

Пожалуйста, проверьте эту тему для большего понимания Что гарантируется относительно размера указателя функции?

0 голосов
/ 01 июня 2013

Вы можете просто использовать простую специализацию шаблонов.

#include <stdio.h>

template<typename T>
struct func_with_zero_args { static const bool value = false; };
template<>
struct func_with_zero_args <int (*)()> { static const bool value = true; };

#define STRINGIFY(t) "" #t
#define TEST(t) printf(STRINGIFY(t) ": %s\n", (func_with_zero_args<t>::value ? "yes" : "no"));

int
main(int argc, const char* argv[])
{
    TEST(void);
    TEST(void (*)(void));
    TEST(void (*)(int));
    TEST(int (*)(void));
    TEST(int (*)(int));
    return 0;
}

Генерирует (используя g ++ (Ubuntu / Linaro 4.7.3-1ubuntu1) 4.7.3)

void: no
void (*)(void): no
void (*)(int): no
int (*)(void): yes
int (*)(int): no
0 голосов
/ 06 января 2012

Проблема не в использовании int().Вы можете полностью удалить это из примера и получить ту же ошибку.Проблема в том, что само выражение sizeof используется в качестве нетипового аргумента шаблона.Пример

template<bool val>
struct boolean { };

template<typename T>
struct is_callable : boolean<sizeof((*(T*)0)()) >= 0>  // Error
{ 
  void Test() 
  {
    auto x = sizeof((*(T*)0)()) >= 0;  // Compiles
  }

}; 

Надеемся, что другой парень C ++ может прийти и определить, является ли это выражение sizeof просто недопустимым в качестве аргумента типа или это просто ограничение в компиляторе MS C ++.

...